博弈论专题——推理与动态规划相关博弈之POJ2484 POJ1740(模仿游戏)

来源:互联网 发布:郑州软件培训机构 编辑:程序博客网 时间:2024/06/05 09:19

本专题题目均来自挑战程序设计竞赛例题和练习

A Funny Game
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 5198 Accepted: 3244

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.) 
 
Figure 1

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

1230

Sample Output

AliceAliceBob


n个硬币围成一个圈,Alice和Bob轮流取出一枚硬币,或者两枚连续的硬币,硬币取走后会留下空位,取走最后一枚硬币的人获胜。

首先,如果只有一枚或者两枚硬币,Alice一定可以全部取走。

如果是三枚或者三枚以上呢?

首先考虑一个问题,如果硬币可以恰好分为状态相同的两组,后手一定可以模仿先手的行为,进而获得胜利。说明这是必败态。

当第一次Alice取走一枚或两枚硬币,Bob一定可以把硬币分为相同的两组。那么Bob必胜。所以就是n大于2则bob胜。

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>using namespace std;const int MAXN =15;int n;int a[MAXN];int main(){    while(scanf("%d",&n)&&n){        for(int i=0;i<n;i++)            scanf("%d",a+i);        sort(a,a+n);        int win=0;        if(n%2==1)            win=1;        else{            for(int i=1;i<n;i+=2){                if(a[i]!=a[i-1]){                    win=1;                    break;                }            }        }        printf("%d\n",win);    }}

A New Stone Game
Time Limit: 1000MS Memory Limit: 30000KTotal Submissions: 5671 Accepted: 3102

Description

Alice and Bob decide to play a new stone game.At the beginning of the game they pick n(1<=n<=10) piles of stones in a line. Alice and Bob move the stones in turn. 
At each step of the game,the player choose a pile,remove at least one stones,then freely move stones from this pile to any other pile that still has stones. 
For example:n=4 and the piles have (3,1,4,2) stones.If the player chose the first pile and remove one.Then it can reach the follow states. 
2 1 4 2 
1 2 4 2(move one stone to Pile 2) 
1 1 5 2(move one stone to Pile 3) 
1 1 4 3(move one stone to Pile 4) 
0 2 5 2(move one stone to Pile 2 and another one to Pile 3) 
0 2 4 3(move one stone to Pile 2 and another one to Pile 4) 
0 1 5 3(move one stone to Pile 3 and another one to Pile 4) 
0 3 4 2(move two stones to Pile 2) 
0 1 6 2(move two stones to Pile 3) 
0 1 4 4(move two stones to Pile 4) 
Alice always moves first. 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

The input contains several test cases. The first line of each test case contains an integer number n, denoting the number of piles. The following n integers describe the number of stones in each pile at the beginning of the game, you may assume the number of stones in each pile will not exceed 100. 
The last test case is followed by one zero. 

Output

For each test case, if Alice win the game,output 1,otherwise output 0. 

Sample Input

32 1 321 10

Sample Output

10


这应该算是难度比较大的推理性质的博弈。每一轮你可以减少任意一堆石子至少一个,可以再从剩下的里面分出一些给其他堆。

也是一个模仿游戏类的题目。

如果石子可以完全分为对称的两部分,那么后手一定通过模仿先手的行为获得胜利。

如果一开始石子对称,那么后手胜。

如果不呢?

那么先手一定可以把石子分为对称的两部分。

为何?

不论石子的堆数是奇数堆还是偶数堆,

都可以通过改变最高的那堆使得石子对称。

把石子按数量排序,相邻的高度差的和一定小于最高的石子。也就是最高的石子可以弥补相邻石子的高度差。


#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>using namespace std;const int MAXN =15;int n;int a[MAXN];int main(){    while(scanf("%d",&n)&&n){        for(int i=0;i<n;i++)            scanf("%d",a+i);        sort(a,a+n);        int win=0;        if(n%2==1)            win=1;        else{            for(int i=1;i<n;i+=2){                if(a[i]!=a[i-1]){                    win=1;                    break;                }            }        }        printf("%d\n",win);    }}







1 0