AOJ0232 Life Game

問題リンク Life Game

  • 解法

DPです。
dp[i][j]: 所持金 i を持ってマス j へ到着する確率
という表をjが小さい方から埋めることで解けます。これは、ゲーム中、後ろのマスへ下がることがないから可能です。
初期値はdp[初期所持金][0] = 1.0となります。
また、最大でもボードは50マス、一度のイベントで手に入る最高金額が100なので、手持ちの金額が5000を超えることはありません。

  • ソース
import java.util.Scanner;

//Life Game
public class AOJ0232 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		while(true){
			int x = sc.nextInt();
			int n = sc.nextInt();
			int e = sc.nextInt();
			if((x|n|e)==0)break;
			int[] v = new int[x];
			for(int i=0;i<x;i++)v[i]=sc.nextInt();
			int[][] ev = new int[n+1][2];
			while(e--!=0){
				int p = sc.nextInt();
				int k = sc.nextInt();
				int val = sc.nextInt();
				ev[p][0] = k;
				ev[p][1] = val;
			}
			double[][] p = new double[5001][n+1];

			p[0][0] = 1;
			for(int i=0;i<n;i++){
				for(int j=0;j<5001;j++){
					if(p[j][i]==0)continue;
					for(int k=0;k<x;k++){
						int np = Math.min(n, i+v[k]);
						int nm = j;
						if(ev[np][0]==1){
							np = Math.min(n, np+ev[np][1]);
						}
						else if(ev[np][0]==2){
							nm += ev[np][1];
						}
						else if(ev[np][0]==3){
							nm = Math.max(0, nm-ev[np][1]);
						}
						p[nm][np] += p[j][i]/x;
					}
				}
			}
			double exp = 0;
			for(int i=0;i<5001;i++)exp+=i*p[i][n];
			System.out.println((int)exp);
		}
	}
}