POJ 2068 Nim (博弈和DP本是一家=-=)

来源:互联网 发布:淘宝全屏店招装修 编辑:程序博客网 时间:2024/05/10 00:57

POJ 2068 Nim

题意:

2n个人围成一圈,编号为奇数的一队,编号为偶数的一队,轮流从原本S个石头的石堆进行拿石头操作

每个人可拿石头范围在[1,m[i]]内(m[i]表示第i个人最多能拿的石头数)

问先手(0所在的偶数队)能否取胜

分析:

dp[i][j]表示第i个人面对j个石头的局面 是否能胜(1/0)
只要有“败”的子状态就是胜态
如果子状态全为胜态则为败态
状态转移:
在dp[(i+1)%2n][j-x]中找败态(x ∈ [1,m[i]])
表示第i个人拿走x个石头,让下一个人
(i+1)%2n面对j-x个石头的局面 

记忆化搜索=-= 

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<vector>#include<algorithm>#define mem(a,x) memset(a,x,sizeof(a))using namespace std;typedef long long ll;const int inf = 0x3f3f3f3f;/*dp[i][j]表示第i个人面对j个石头的局面 是否能胜只要有“败”的子状态就是胜态如果子状态全为胜态则为败态状态转移:在dp[(i+1)%2n][j-x]中找败态表示第i个人拿走x个石头,让第(i+1)%2n个人面对j-x个石头的局面 记忆化搜索=-= */int dp[22][1<<14]; int m[22];int n,s;int DP(int i,int j){if (j == 0) return 1;//没有石头的局面为胜态 if (~dp[i][j]) return dp[i][j];for (int x = 1;x <= m[i];++x){if (j-x<0) break;if (DP((i+1)%(2*n),j-x) == 0) return dp[i][j] = 1;}return dp[i][j] = 0;} int main(){while (cin>>n){if (!n) break;cin>>s;for (int i = 0;i < 2*n;++i) cin>>m[i];mem(dp,-1);cout<<DP(0,s)<<endl;}return 0;}
java:
//package acm.poj2068;import java.util.*;public class Main {static int n , s;static int dp[][] = new int[22][1<<14];static int m[] = new int [22];static void init(){for (int i = 0;i <= 2*n;++i){Arrays.fill(dp[i], -1);}}static int DP(int i,int j){if (j == 0) return 1;if (dp[i][j]!=-1) return dp[i][j];for (int x = 1;x <= m[i];++x){if (j-x<0) break;if (DP((i+1)%(2*n),j-x) == 0) return dp[i][j] = 1;}return dp[i][j] = 0;}public static void main(String[] args) {// TODO Auto-generated method stub@SuppressWarnings("resource")Scanner in = new Scanner(System.in);while (in.hasNext()){n = in.nextInt();if (n == 0) break;s = in.nextInt();for (int i = 0;i < 2*n;++i){m[i] = in.nextInt();}init();System.out.println(DP(0,s));}}}


0 0
原创粉丝点击