Apple。好题!ACdream群赛

题目链接:http://acdream.info/problem?pid=1131

题意:状态:有n个篮子和m个苹果,他们每一个都是不同的。然后给出一个数A,有A,B两个人轮流进行操作,每次只能增加1个篮子或者1个苹果,操作完之后如果这m个苹果放到n个篮子的方式(设为k),篮子可以为空,如果这个k不小于A的值的话,就算这个人输了。当然这两个人都是聪明人,都会尽力不会让自己输。

输出结果Alice是赢还是输或者平局。win,lose,draw.

解题思路:刚开始看题目Alice和bob还以为是博弈论,纠结一会,后来慢慢发现了点什么。首先我们得知道m个不同的苹果放到n个不同的篮子有多少种方法。每个苹果放进篮子有n种方法,一共有m个,所以方法数k=n*n*n...(n的m次方)。

然后我的方法是搜索,DFS(n+1,m,t),DFS(n,m+1,t)的两种状态,t=0或1意思是代表当前是A或者B进行操作。每次把这两种状态的k算出来,也就是pd(n+1,m),pd(n,m+1)判断是否小于A,如果大于等于A,肯定就Gg,再结合当前t(也就是谁进行操作)判断是赢还是输,当这两种状态都有一个返回值0或者1。0代表A会输,反之同理。当前状态是A操作的话,只要两个状态有一个为1,则当前状态为1,若当前状态是B操作的话,只有后续两个状态都为1,当前状态才为1。注意这里的DFS返回值0,1代表A是否输赢。从最后状态一直推到最先状态即可知道输赢。写到这里,大部分流程已经完成了。不知有没有注意到这里会出现一个平局状态。所以这里有一个特判。当篮子数为1的时候。如果增加篮子数超过A的话,那聪明的A,B肯定不会去选,所以只能增加苹果数,结果会导致平局。然后如果篮子数为1,A增加篮子数这时候状态就变成(2,m)转移给B,这时相当于B于这个状态开始游戏,若此状态是必输,则A肯定赢了。如果是必赢,则A肯定会去选择苹果数+1,状态变为(1,m+1)转移给B,B再进行同样的抉择,所以当篮子数等于1的时候,需要去特判这种情况。啊,好麻烦。。。有理也讲不清了。GG,直接上代码了。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <list>
#include <vector>
using namespace std;
//#define DEBUG
int n,m,a;
int pd(int n,int m)
{
	long long s=1;
	for (int i=1;i<=m;i++)
	{	
		s=s*n;
		if (s>=a) return 1;
	}
	return 0;	
}
int f;
int DFS(int n,int m,int t)
{
	int f1,f2,h1,h2;
	h1=pd(n+1,m);
	h2=pd(n,m+1);
	if (h1 && h2) 
	{
		if (t==1) return 1;
		else return 0;
	}
	if (h1) 
	{
		if (t==1) f1=1;
		else f1=0;
	}
	else f1=DFS(n+1,m,(t+1)%2);
	if (h2)
	{
		if (t==1) f2=1;
		else f2=0;
	}
	else f2=DFS(n,m+1,(t+1)%2);
	if (t==0)
	if (f1+f2) return 1;
	else return 0;
	if (t==1)
	{
		if (f1+f2==2) return 1;
		else return 0;
	}
}
int main()
{
#ifdef DEBUG
	freopen("cin.txt", "r", stdin);
	freopen("cout.txt", "w", stdout);
#endif
//	scanf("%d%d%d",&n,&m,&a);
	while (~scanf("%d%d%d",&n,&m,&a))
	{
	if (n==1) 
	{
		int tt=0,flag=0;
		while (pd(2,m)==0 && !pd(n,m+1))
		{
				if (DFS(2,m,0)==0) 
				{
					if (tt==0)
						printf("win\n");
					else printf("lose\n");
					flag=1;
					break;
				}
				else m++;
				tt=(tt+1)%2;
		}
		if (flag==0) printf("draw\n");
	}
	else
    {
    	if (DFS(n,m,0)) printf("win\n");
		else printf("lose\n");
	}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值