ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준 16920] 확장 게임
    C 프로그래밍/BOJ 2022. 12. 8. 11:39
    728x90

    https://www.acmicpc.net/problem/16920

     

    16920번: 확장 게임

    구사과와 친구들이 확장 게임을 하려고 한다. 이 게임은 크기가 N×M인 격자판 위에서 진행되며, 각 칸은 비어있거나 막혀있다. 각 플레이어는 하나 이상의 성을 가지고 있고, 이 성도 격자판 위

    www.acmicpc.net

    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <vector>
    int R, C, P;
    char board[1000 + 2][1000 + 2];
    
    struct _vt
    {
    	int x, y;
    	int move;
    };
    
    struct _st
    {
    	bool spread;
    	int speed;
    	int castle;	// 성좌표를 굳이 벡터에 저장할 필요 없음 .. 
    };
    _st Player[9 + 2];
    
    std::queue<_vt> Q[9 + 2];
    std::queue<_vt> TMP;
    int visited[1000 + 2][1000 + 2];
    
    void input()
    {
    	scanf("%d %d %d", &R, &C, &P);
    	for (int i = 1; i <= P; i++) {
    		scanf("%d", &Player[i].speed);
    	}
    
    	for (int r = 0; r < R; r++) {
    		scanf("%s", &board[r]);
    		for (int c = 0; c < C; c++) {
    			if (board[r][c] >= '1' && board[r][c] <= '9') {	// 숫자인것만 받아주어야 함 !!! 벽이 있을 수 잇다 
    				int p_num = board[r][c] - '0';
    				Q[p_num].push({ r, c , 0});
    				visited[r][c] = p_num;
    				Player[p_num].castle++;
    			}
    		}
    	}
    }
    
    // 버퍼큐 놓고 큐 계속 갈아 끼우면 그 횟수가 1000번이 넘어갈 때는 시간초과 날 수 있다.. 
    void BFS(int p_num)
    {
    	// dir
    	int dir_x[4] = { 0, 0 ,1 ,-1 };
    	int dir_y[4] = { 1, -1, 0, 0 };
    
    	// init
    	TMP = {};
    	bool now = false;
    
    	if (Q[p_num].empty()) {
    		Player[p_num].spread = false;
    		return;
    	}
    
    	while (!Q[p_num].empty()) {
    		_vt data = Q[p_num].front();
    		Q[p_num].pop();
    
    		for (int p = 0; p < 4; p++) {
    			int nx = data.x + dir_x[p];
    			int ny = data.y + dir_y[p];
    
    			if (nx < 0 || nx > R - 1 || ny < 0 || ny > C - 1) continue;
    			if (board[nx][ny] == '#')continue;
    			if (visited[nx][ny]) continue;
    			if (data.move + 1 == Player[p_num].speed) TMP.push({ nx, ny, 0 });
    			else Q[p_num].push({ nx, ny, data.move + 1 });
    			visited[nx][ny] = p_num;
    			Player[p_num].castle++;
    			now = true;
    		}
    	}
    	Q[p_num] = TMP;
    	Player[p_num].spread = now;
    }
    
    
    
    
    bool chk_done()
    {
    	for (int i = 1; i <= P; i++) {
    		if (Player[i].spread == true) return false;
    	}
    	return true;	// 모든 플레이어가 더 이상 확장을 할 수 없을 때 게임이 끝난다. 
    }
    
    
    void simulation()
    {
    	while (1) {
    		// move players
    		for (int i = 1; i <= P; i++) {
    			BFS(i);
    		}
    		//debug();
    		// chk
    		if (chk_done()) return;
    	}
    }
    
    void output()
    {
    	for (int i = 1; i <= P; i++) {
    		printf("%d ", Player[i].castle);
    	}
    	printf("\n");
    }
    
    
    int main()
    {
    	input();
    	simulation();
    	output();
    	return 0;
    }

    1. 3번의 oob는 인풋 받을 때 벽이 있는 경우를 생각 못하고 board[r][c] != '.' 일때 구조체에 담으라고 했기 때문이다.. 

    이런거 설계 좀 잘하자.. 어떤 것들이 입력 받아지는지 잘 생각하면서 코드 짜자.. 

     

    2. 시간초과가 난 이유는 버퍼큐를 큐 돌릴 때 마다 갈아끼워주었기 때문이다. 최악의 경우 1000 * 1000 맵에서 Si가 1000일 때 그만큼 큐를 계속 갈아끼워준것.. 

    해결한 방법은 상태를 발전시킬 맨 마지막 원소들(해당 문제에서는 data.move + 1 == Player[p_num].speed) 만 버퍼큐에 넣어놓고 큐가 비어서 루프를 빠져나오면 가장 마지막에 한 번 갈아끼워주는 것이다. 

    이때도 주의해야할 점.. data.move 가 아니라 data.move + 1 이랑 비교해주어야 한다.. 왜냐하면 (nx, ny)이니까 현재에서 한 칸 이동한 다음 좌표이므로 move 수도 한 칸 늘어남....

    728x90

    'C 프로그래밍 > BOJ' 카테고리의 다른 글

    [백준 17406] 배열 돌리기4  (0) 2022.12.11
    [백준 6593] 상범 빌딩  (0) 2022.12.07
    [백준 22255] 호석사우루스  (0) 2022.12.06
    [백준 8972] 미친 아두이노  (0) 2022.12.06
    [백준 1261] 알고스팟  (0) 2022.12.06

    댓글

Designed by Tistory.