AOJ1230 Nim
問題リンク Nim
- 概要
Nimというゲームをやる。石の山から石を1〜4個交代でとっていき、最後の1個を取った人が負けである。
ただ、今回のNimは少しルールが違う。
まず、チームでプレイする。1チームはN人であり、全部で2N人でプレイする。石を取る順番は味方チームの1人目、相手チームの1人目、味方チームの2人目...とする。
そして、石を取る個数の上限 Mi が人によってバラバラである。
今石の数がS個であるとき、味方のチームが必ず勝つ戦略は存在するかを調べる。存在するなら1, そうでないならば0と答えよ
N<=10
S<=2^13
Mi<=16
- 解法
DPで解きます。
dp[i][j]: 残りの石の個数が j のときに i のターンが来た時に最善の戦略を取った時、勝つか負けるか
dp[i][1] は残りの石が1個しかないので必ず負けます。
dp[i][j] をどう埋めるかですが、この人が1〜m個の石を取れるとき、dp[i+1][j-k] (1<=k<=m)を見ていき、この中に1つでもfalse (=負ける)があれば、この人は k 個の石を取ることで必ず勝つことができます。それ以外なら負けます。
このdpの表を石の残り数が少ない方から埋めていき、dp[0][S]がtrueならば必ず勝つ戦略があると分かります。
- ソース
import java.util.Scanner; //Nim public class AOJ1230 { void run(){ Scanner sc = new Scanner(System.in); for(;;){ int n = sc.nextInt(); if(n==0)break; int s = sc.nextInt(); int[] m = new int[2*n]; for(int i=0;i<2*n;i++)m[i]=sc.nextInt(); boolean[][] dp = new boolean[2*n][s+1]; for(int j=2;j<=s;j++)for(int i=0;i<2*n;i++){ boolean w = false; for(int p=1;p<=m[i];p++){ if(j-p<=0)break; if(!dp[(i+1)%(2*n)][j-p])w=true; } dp[i][j] = w; } System.out.println(dp[0][s]?1:0); } } public static void main(String[] args) { new AOJ1230().run(); } }