P9862 [CCC 2008 J5/S5] Nukit 题解
其实题面少了一句话:假设两人都足够聪明,我们给它加上。
首先,在博弈中,我们明确三个性质:
- 如果一个状态的后继有一个必败状态,则该状态为必胜状态。
- 如果一个状态的后继全都是必胜状态,则该状态为必败状态。
- 不能再取的状态为必败状态(即:不能再取的状态的后继全都是必胜状态)。
一般的博弈论题都是可以通过这两条从
不知道为什么清空 dp 数组的时候不能用 memset,我在这里寄了十分钟。
根据以上性质,我们可以写出这样一份代码:
#include<bits/stdc++.h>
using namespace std;
int t,a,b,c,d,dp[31][31][31][31];
bool dfs(int a,int b,int c,int d){
if(a<0||b<0||c<0||d<0) return 1;//不能再取的状态的后继全都是必胜状态
if(dp[a][b][c][d]!=-1) return dp[a][b][c][d];
if(dfs(a-2,b-1,c,d-2)&&dfs(a-1,b-1,c-1,d-1)&&dfs(a,b,c-2,d-1)&&dfs(a,b-3,c,d)&&dfs(a-1,b,c,d-1)) dp[a][b][c][d]=0;//如果一个状态的后继全都是必胜状态,则该状态为必败状态。
else dp[a][b][c][d]=1;//如果一个状态的后继有一个必败状态,则该状态为必胜状态。
return dp[a][b][c][d];
}
int main(){
cin>>t;
while(t--){
for(int i=0;i<=30;i++) for(int j=0;j<=30;j++) for(int k=0;k<=30;k++) for(int l=0;l<=30;l++) dp[i][j][k][l]=-1;
cin>>a>>b>>c>>d;
if(dfs(a,b,c,d)) cout<<"Patrick"<<endl;
else cout<<"Roland"<<endl;
}
}