题意:
就是给你0,1,2,3,这四个数的个数。然后你每次可以选择两个数加起来,不过加起来的值要<=3,然后丢掉选择的两个数字,把这个加起来的值放进去。小A和小B轮流操作,小A先操作。最后不能操作的人输。问你谁赢。
思考:
- 当时就感觉可能不是太简单?就没想去思考。其实这种博弈题,也不用一味着去想到底谁操作谁咋操作。先把那种不管是谁都可以操作的次数拿出来,消掉,(不过这有点猜的成分,因为也完全可以往别的方面转化,但是往这个转化比较方便看)
- 可以发现,0随意操作,也就是小A用一次0小B用一次0,所以当0是偶数的时候一人一次就用没了,所以就直接cnt[0]%2,那些可以抵消掉的次数都抵消掉。对于1呢,发现1+1=2,1+2=3,也就是3个1可以操作两次。所以每3个1也都消掉。对于最后的状态,去暴力搜索一下,看看先手是否可以赢。
- 值得注意的是,虽然2和3只是看有没有,所以当1和2和3都为0的时候,这时候要特判,只能操作cnt[0]-1次。对于暴力搜索呢,比如到这一次了,肯定会按自己最优的去搜,也就是看看我的集中操作,可以让下一次搜索返回0,也就是下一个人是必败态。那么我就可以成为必胜态。如果没有,那么我就这个就是必败态。这样才能保证搜索的正确性,每次搜索都是要按自己最好的方式去走。
代码:
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define db double
#define int long long
#define PII pair<int,int >
#define mem(a,b) memset(a,b,sizeof(a))
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
const int mod = 1e9+7,inf = 1e18;
const int N = 2e5+10,M = 2010;
int T,n,m,k;
int va[N];
bool dfs(int a0,int a1,int a2,int a3)
{
if(a0>=1&&!dfs(a0-1,a1,a2,a3)) return 1;
if(a1>=1&&a2>=1&&!dfs(a0,a1-1,a2-1,a3+1)) return 1;
if(a1>=2&&!dfs(a0,a1-2,a2+1,a3)) return 1;
return 0;
}
signed main()
{
IOS;
cin>>T;
for(int cs=1;cs<=T;cs++)
{
cout<<"Case #"<<cs<<": ";
int a,b,c,d;
cin>>a>>b>>c>>d;
if(!b&&!c&&!d)
{
if(a==0) cout<<"Horse";
else
{
if((a-1)&1) cout<<"Rabbit";
else cout<<"Horse";
}
if(cs!=T) cout<<"\n";
}
else
{
int now = dfs(a%2,b%3,c,d);
if(now==1) cout<<"Rabbit";
else cout<<"Horse";
if(cs!=T) cout<<"\n";
}
}
return 0;
}
总结:
多多思考总结,大胆尝试。