POJ 2484(博弈-对称博弈)

A Funny Game
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 3345   Accepted: 1960

Description

Alice and Bob decide to play a funny game. At the beginning of the game they pick n(1 <= n <= 106) coins in a circle, as Figure 1 shows. A move consists in removing one or two adjacent coins, leaving all other coins untouched. At least one coin must
be removed. Players alternate moves with Alice starting. The player that removes the last coin wins. (The last player to move wins. If you can't move, you lose.) 
 

Note: For n > 3, we use c1, c2, ..., cn to denote the coins clockwise and if Alice remove c2, then c1 and c3 are NOT adjacent! (Because there is an empty place between c1 and c3.) 

Suppose that both Alice and Bob do their best in the game. 
You are to write a program to determine who will finally win the game.

Input

There are several test cases. Each test case has only one line, which contains a positive integer n (1 <= n <= 106). There are no blank lines between cases. A line with a single 0 terminates the input. 

Output

For each test case, if Alice win the game,output "Alice", otherwise output "Bob". 

Sample Input

1
2
3
0

Sample Output

Alice
Alice
Bob

Source

POJ Contest,Author:Mathematica@ZSU

博弈第一招——对称博弈。

思路:无论对方怎么取,我都取与它对称(或者相反/一样的)

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cstring>
#include<iostream>
using namespace std;
int main()
{
	int n;
	while(scanf("%d",&n)&&n)
	{
		if (n>=3) cout<<"Bob"<<endl;
		else cout<<"Alice"<<endl;
	}
	return 0;
}

放球游戏(a^b博弈)

Problem 3 放球游戏(ball.cpp/c/pas)

【题目描述】

     Stas和Masha发明了一个游戏。游戏道具是a个两两不同的箱子和b个两两不同的皮球,Stas和Masha轮流操作,且每次操作新增一个完全不同的箱子或皮球。如果Stas或Masha操作了以后,把b个皮球放进a个箱子的方案数不小于n,那么这个人就会输掉。所有箱子和皮球都是不同的,可以有空的箱子。
  如果第一回合由Stas先操作,且Stas和Masha都按照最优策略进行游戏,那么是否会打平?如果不打平,谁会输??

【输入格式】

输入的第一行包含三个正整数a,b,n。

【输出格式】

如果Stas会输,输出'Stas'(不要输出引号);如果Masha会输,输出'Masha';   如果游戏会打平(也就是不结束),输出'Missing'。

【样例输入】

样例一:2 2 10

样例二:5 5 16808

样例三:3 1 4

样例四:1 4 10

 

【样例输出】

样例一:Masha

样例二:Masha

样例三:Stas

样例四:Missing

【数据范围】

对于10%的数据,n不超过10;
    对于30%的数据,n不超过10000。

对于100%的数据,1≤a≤10,000, 1≤b≤30, 2≤n≤1,000,000,000, a^b<n

博弈a^b=n

把a>1的所用情况记忆化(情况数少)

唯一平局的情况是

a=1 b=x 

(a+1)^b爆 

还有一种是

1^x 2^x爆 判奇偶

其实不记忆化也能过(汗-_-)。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<functional>
#include<cstdlib>
#include<cmath>
#include<iostream>
using namespace std;
#define MAXN (1000000000)
#define MAXA (10000+10)
#define MAXB (30+10)
long long a,b,n;
bool pow2(long long a,long long b)
{
	long long ans=1;
	for(int i=1;i<=b;i++)
	{
		ans*=a;
		if (ans>=n) return 0;
	}
	return 1;
}
int dfs(long long a,long long b) //a,b状态保证合法 0 Miss 1 Win -1 Lost
{
	if (a==1&&!pow2(a+1,b)) return 0;
	int flag=-1;
	if (a==1)
	{
		if (pow2(a+1,b)) flag=max(-dfs(a+1,b),flag);
		if (flag==1) return 1;
		if (pow2(a,b+1)) flag=max(-dfs(a,b+1),flag);
		return flag;
	}
	else
	{
		if (pow2(a,b+1)) flag=max(-dfs(a,b+1),flag);
		if (flag==1) return 1;
		if (pow2(a+1,b)) flag=max(-dfs(a+1,b),flag);
		return flag;
	}
}
int main()
{
	freopen("ball.in","r",stdin);
	freopen("ball.out","w",stdout);
	scanf("%d%d%d",&a,&b,&n);
	/*
	if (a==1&&!pow2(a+1,b))
	{

		return 0;
	}
	else if (b==1&&!dfs(a,b+1))
	{

	}
	*/
	int p=dfs(a,b);
	if (p==0) printf("Missingn");
	else if (p==-1) printf("Stasn");
	else printf("Mashan");
	return 0;
}

环上的游戏(贪心-博弈)

环上的游戏(cycle

有一个取数的游戏。初始时,给出一个环,环上的每条边上都有一个非负整数。这些整数中至少有一个0。然后,将一枚硬币放在环上的一个节点上。两个玩家就是以这个放硬币的节点为起点开始这个游戏,两人轮流取数,取数的规则如下:

(1)选择硬币左边或者右边的一条边,并且边上的数非0;

(2)将这条边上的数减至任意一个非负整数(至少要有所减小);

(3)将硬币移至边的另一端。

如果轮到一个玩家走,这时硬币左右两边的边上的数值都是0,那么这个玩家就输了。

如下图,描述的是Alice和Bob两人的对弈过程,其中黑色节点表示硬币所在节点。结果图(d)中,轮到Bob走时,硬币两边的边上都是0,所以Alcie获胜。

现在,你的任务就是根据给出的环、边上的数值以及起点(硬币所在位置),判断先走方是否有必胜的策略。

 

【输入格式】

第一行一个整数N(N≤20),表示环上的节点数。

第二行N个数,数值不超过30,依次表示N条边上的数值。硬币的起始位置在第一条边与最后一条边之间的节点上。

 

【输出格式】

仅一行。若存在必胜策略,则输出“YES”,否则输出“NO”。

 

【样例】

cycle.incycle.out

4 YES

2 5 3 0

cycle.incycle.out

3 NO

0 0 0

最后取到数的人获胜

稍加模拟

不难发现

0-x-x-x-x-x-x-1-x-x-x-x-x-0

显然任意取一个数,若全取,则

0-10-10-0

  ↑

对方再取 0- 9-10-0

我记续取 0- 9-0-0

    ↑

想办法让对方只能向一个方向取

0-x-x-x-x-0

  ↑

此时奇数次必胜,偶数次必败

若两个方向都是偶数个x

0-x-x-x-x- 0

        ↑

此时无论我怎么取

0-x-(x-?)-x-x-0

     ↑   

于是又成了必胜态,故上次为必败态

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<functional>
#include<algorithm>
using namespace std;
#define MAXN (20+10)
int n;
int a[MAXN];
bool flag=0;
int main()
{
	freopen("cycle.in","r",stdin);
	freopen("cycle.out","w",stdout);

	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	int i=1; while (a[i]) i++;
	if ((i-1)%2) flag=1;
	i=n; while (a[i]) i--;
	if ((n-i)%2) flag=1;

	if (flag) printf("YESn");
	else printf("NOn");

//	while (1);
	return 0;
}