2020绵阳-Game of Cards-(博弈论+搜索)

60 篇文章 1 订阅
54 篇文章 2 订阅

G

题意:
就是给你0,1,2,3,这四个数的个数。然后你每次可以选择两个数加起来,不过加起来的值要<=3,然后丢掉选择的两个数字,把这个加起来的值放进去。小A和小B轮流操作,小A先操作。最后不能操作的人输。问你谁赢。

思考:

  1. 当时就感觉可能不是太简单?就没想去思考。其实这种博弈题,也不用一味着去想到底谁操作谁咋操作。先把那种不管是谁都可以操作的次数拿出来,消掉,(不过这有点猜的成分,因为也完全可以往别的方面转化,但是往这个转化比较方便看)
  2. 可以发现,0随意操作,也就是小A用一次0小B用一次0,所以当0是偶数的时候一人一次就用没了,所以就直接cnt[0]%2,那些可以抵消掉的次数都抵消掉。对于1呢,发现1+1=2,1+2=3,也就是3个1可以操作两次。所以每3个1也都消掉。对于最后的状态,去暴力搜索一下,看看先手是否可以赢。
  3. 值得注意的是,虽然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;
}

总结:
多多思考总结,大胆尝试。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值