【博弈 && dfs】POJ
阿新 • • 發佈:2019-01-25
Step1 Problem:
有 s 個石頭,有 2*n 個人,分成兩隊交叉坐著分別是 1, 3, 5,…n-1. 和 2, 4, 6,…n. 第 i 個人可以拿走不多於 a[i] 個石頭,從玩家 1 開始拿石頭 1 到 2 到 3 到….n 到 1 一直迴圈,拿走最後一顆石頭的團隊失敗。
資料範圍:
1<=n<=10, 1<=a[i]<=16, 1<=s<=2^13
Step2 Ideas:
dp[s][i] == 1:當前到玩家 i 剩餘 s 個石頭必勝
dp[s][i] == 0:當前到玩家 i 剩餘 s 個石頭必敗
dp[s][0] 就是結果
當前狀態的下一個狀態是必敗狀態,當前狀態為必勝狀態。
當前狀態的下一個狀態全是必勝狀態,當前狀態為必敗狀態。
然後搜尋即可
Step3 Code:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 9000;
const int inf = 0x3f3f3f3f;
int a[100];
int dp[N][25], s, n;
int dfs(int x, int i)//剩餘的石子,到第幾個人
{
//printf("%d %d\n", x, i);
if(x <= 0) return dp[0][i] = 1;//已經沒有石子可拿,所以當前狀態必勝
if(dp[x][i] != -1) return dp[x][i];//已經搜尋過了不必再搜尋了
int res = inf;
for(int j = 1; j <= a[i] && j <= x; j++)
{
res = min(res, dfs(x-j, (i+1)%(2*n)));
}
if(res == 0) return dp[x][i] = 1;//下一個狀態存在必敗狀態,當前狀態必勝
else return dp[x][i] = 0;
}
int main()
{
while(~scanf ("%d", &n) && n)
{
memset(dp, -1, sizeof(dp));
scanf("%d", &s);
for(int i = 0; i < 2*n; i++)
scanf("%d", &a[i]);
dfs(s, 0);
printf("%d\n", dp[s][0]);
}
return 0;
}