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

  • 문제 정리
  1. N x M 짜리 격자판 위에서 플레이어 P명이 게임을 한다.
  2. 매 라운드마다 플레이어 1부터 오름차순으로 턴이 진행되는데, 각 턴에 플레이어 i는 최대 Si 만큼 이동해서 도달할 수 있는 모든 칸으로 확장 한다.
  3. 더 이상 확장할 수 있는 플레이어가 없을 때 게임을 종료하고 그 때의 상태를 구한다.
  • 정답 코드
import java.util.*;
import java.io.*;
public class Main {
	static int[][] a;
	static boolean[][] c;
	static int[] s;
	static int[] dx = {1,-1,0,0};
	static int[] dy = {0,0,1,-1};
	static int n,m,p;
	static int[] ans;
	static final int MAX = 1000000;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		n = Integer.parseInt(st.nextToken());
		m = Integer.parseInt(st.nextToken());
		p = Integer.parseInt(st.nextToken());
		a = new int[n][m];
		c = new boolean[n][m];
		s = new int[p+1];
		ans = new int[p+1];
		st = new StringTokenizer(br.readLine());
		for(int i=1; i<=p; i++) {
			s[i] = Integer.parseInt(st.nextToken());
			if(s[i]>MAX) s[i] = MAX;
		}
		LinkedList<Pair>[] list = new LinkedList[p+1];
		for(int i=1; i<=p; i++) list[i] = new LinkedList<Pair>();
		for(int i=0; i<n; i++) {
			String in = br.readLine();
			for(int j=0; j<m; j++) {
				char ch = in.charAt(j);
				if(ch == '#') {
					a[i][j] = -1;
				}else if(ch == '.') {
					a[i][j] = 0;
				}else {
					a[i][j] = ch-'0';
					list[a[i][j]].add(new Pair(i,j));
					ans[a[i][j]]++;
				}
			}
		}
		while(true) {
			for(int i=1; i<=p; i++) {
				int e = 0;
				while(list[i].size() > 0) {
					int ls = list[i].size();
					while(ls-- > 0) {
						Pair p = list[i].poll();
						for(int k=0; k<4; k++) {
							int ni = p.i + dx[k];
							int nj = p.j + dy[k];
							if(ni < 0 || ni >=n || nj < 0 || nj >= m) continue;
							if(a[ni][nj] != 0) continue;
							ans[i]++;
							list[i].add(new Pair(ni,nj));
							a[ni][nj] = i;
						}
					}
					e++;
					if(e == s[i]) break;
				}
			}
			boolean ok = true;
			for(int i=1; i<=p; i++) {
				if(list[i].size() > 0) ok = false;
			}
			if(ok) break;
		}
		for(int i=1; i<=p; i++) {
			System.out.print(ans[i]);
			if(i != p) System.out.print(' ');
		}
	}
	static class Pair{
		int i, j;
		public Pair(int i, int j) {
			this.i = i;
			this.j = j;
		}
	}
	static class Cas{
		int len, i, j;
		public Cas(int len, int i, int j) {
			this.len = len;
			this.i = i;
			this.j = j;
		}
	}
}

  • 오답 노트

    처음 문제를 풀었을 때 일반적인 BFS 문제와 똑같이 하나의 queue를 사용해 확장해야할 좌표를 저장했다.

LinkedList<Pnt> list = new LinkedList<Pnt>();

이 때 사용된 Pnt 클래스는 플레이어 번호도 가지고 있다.

	static class Pnt{
		int pl, i, j;
		public Pnt(int pl, int i, int j) {
			this.pl = pl;
			this.i = i;
			this.j = j;
		}
	}

이렇게 문제를 푸니 틀렸습니다 를 받았는데,

그 이유는 queue를 하나만 사용해서 넣어주게 되면 한 플레이어가 가진 여러 성이 한 턴에서 확장을 할 때 서로 영향을 주기 때문이다.

자세한 설명은 https://www.acmicpc.net/board/view/35413 질문 글에서 확인할 수 있다.