AOJ2332 Space-Time Sugoroku Road

問題リンク Space-Time Sugoroku Road

  • 解法

マスiに停まったら最終的にどのマスへ行くのか、もしくはループに陥るのかを前計算します。あとは、これを使って幅優先探索します。

  • ソース
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;

//Space-Time Sugoroku Road
public class AOJ2332 {

	void run(){
		int LOOP = 1<<29;
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int[] p = new int[n], nx = new int[n];
		Arrays.fill(nx, -1);
		for(int i=0;i<n;i++)p[i]=sc.nextInt();
		for(int i=0;i<n;i++){
			if(nx[i]!=-1)continue;
			if(p[i]==0){
				nx[i] = i; continue;
			}
			Set<Integer> s = new HashSet<Integer>();
			s.add(i);
			int v = i+p[i], r = 0;
			for(;;){
				if(nx[v]!=-1){
					r = nx[v]; break;
				}
				if(p[v]==0){
					r = v; s.add(v); break;
				}
				if(s.contains(v)){
					r = LOOP; s.add(v); break;
				}
				s.add(v);
				v+=p[v];
			}
			for(int x:s)nx[x] = r;
		}
		boolean[] u = new boolean[n];
		u[0] = true;
		List<Integer> l = new ArrayList<Integer>();
		l.add(0);
		int step = 0;
		while(!l.isEmpty()){
			List<Integer> next = new ArrayList<Integer>();
			for(int v:l){
				if(v==n-1){
					System.out.println(step); next.clear(); break;
				}
				for(int k=1;k<=6;k++){
					if(n<=v+k)break;
					int t = nx[v+k];
					if(t==LOOP||u[t])continue;
					u[t] = true; next.add(t);
				}
			}
			l = next;
			step++;
		}
	}
	
	public static void main(String[] args) {
		new AOJ2332().run();
	}
}