hdu 5165 Funny Game (博弈)

hdu 5165 Funny Game (博弈)

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5165

题意:

Bob有一个数组{a1,a2,...,an},数组中的每个元素都是介于1到n之间的整数。Bob还有m个函数,他们的定义域和值域都是集合{1,2,...,n}。Bob和Alice轮流开始玩游戏,Alice先开始。对于每一轮,玩家可以选择一个函数f使得数组中每个元素 ai(1 <= i <= n)变成f(ai)。例如,一开始数组是{1,1,2,4,5},有一个函数f(1)=1,f(2)=3,f(3)=4,f(4)=1,f(5)=2。那么经过一次操作,数组变为{1,1,3,1,2}。如果数组中的所有元素都相同(无论当前论是Bob还是Alice),那么Alice胜利游戏结束。然后Bob的目的是阻止Alice胜利。
假设Alice和Bob都足够聪明,每次都采取最优策略。问:无论数组的初始状态是什么,Alice是否都能够必胜?

输入描述:

输入第一行包含一个整数T(1 <= T <= 200)表示测试数据组数。对于每组测试数据:第一行包含两个整数n和m(1 <= n,m <= 100)表示数组的大小和函数的个数。接下来m行,每行包含n个整数f(1),f(2),...,f(n) (1 <= f(i) <= n,1 <= i <= n)。

输出描述:

对于每组数据,如果Alice一定能够必胜,输出YES,否则输出NO。

思路:

1.对于Alice,如果对于每个数对(x,y),都能通过某些函数把它变成(z,z),则Alice必胜,因为由于函数不能一对多,所以这个过程是不可逆的,所以当Alice把(x,y)变成(z,z),Bob不能把它复原,或者变成不一样的数。

2.设(x,y)通过某些函数转换为(z,z)为过程1。

由必胜态倒推,可以看出如果x==y,过程1总是可以成功的。

设dp[x][y][0/1]为对于数对(x,y),Alice先手0,后手1,过程1成功则dp[x][y][0/1]=1,否则dp[x][y][0/1]=0。

所以,在最初的时候dp[i][i][0/1]==1。

我们把dp[x][y][0/1]==1的全部入队,每次取最前面的一个,进行更新,更新分成两种情况:

a)如果Alice此时为先手,则它的前驱为Bob先手。

设Bob先手为事件A,要使事件A的过程1可以成功,则事件A的所有后继的过程1都是成功的。

b)如果Alice此时为后手,则它的前驱为Alice先手。

设Alice先手为事件B,要使事件B的过程1可以成功,则事件B的一个后继的过程1可以成功就行了。

所以一开始建图的时候要建一个正向的图,一个方向的图。

C++ Code


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125


/*hdu 5165

题意:

Bob有一个数组{a1,a2,...,an},数组中的每个元素都是介于1到n之间的整数。Bob还有m个函数,他们的定义域和值域都是集合{1,2,...,n}。Bob和Alice轮流开始玩游戏,Alice先开始。对于每一轮,玩家可以选择一个函数f使得数组中每个元素 ai(1 <= i <= n)变成f(ai)。例如,一开始数组是{1,1,2,4,5},有一个函数f(1)=1,f(2)=3,f(3)=4,f(4)=1,f(5)=2。那么经过一次操作,数组变为{1,1,3,1,2}。如果数组中的所有元素都相同(无论当前论是Bob还是Alice),那么Alice胜利游戏结束。然后Bob的目的是阻止Alice胜利。 假设Alice和Bob都足够聪明,每次都采取最优策略。问:无论数组的初始状态是什么,Alice是否都能够必胜?

输入描述:

输入第一行包含一个整数T(1 <= T <= 200)表示测试数据组数。对于每组测试数据:第一行包含两个整数n和m(1 <= n,m <= 100)表示数组的大小和函数的个数。接下来m行,每行包含n个整数f(1),f(2),...,f(n) (1 <= f(i) <= n,1 <= i <= n)。

输出描述:

对于每组数据,如果Alice一定能够必胜,输出YES,否则输出NO。

思路:

1.对于Alice,如果对于每个数对(x,y),都能通过某些函数把它变成(z,z),则Alice必胜,因为由于函数不能一对多,所以这个过程是不可逆的,所以当Alice把(x,y)变成(z,z),Bob不能把它复原,或者变成不一样的数。

2.设(x,y)通过某些函数转换为(z,z)为过程1。

由必胜态倒推,可以看出如果x==y,过程1总是可以成功的。

设dp[x][y][0/1]为对于数对(x,y),Alice先手0,后手1,过程1成功则dp[x][y][0/1]=1,否则dp[x][y][0/1]=0。

所以,在最初的时候dp[i][i][0/1]==1。

我们把dp[x][y][0/1]==1的全部入队,每次取最前面的一个,进行更新,更新分成两种情况:

a)如果Alice此时为先手,则它的前驱为Bob先手。

设Bob先手为事件A,要使事件A的过程1可以成功,则事件A的所有后继的过程1都是成功的。

b)如果Alice此时为后手,则它的前驱为Alice先手。

设Alice先手为事件B,要使事件B的过程1可以成功,则事件B的一个后继的过程1可以成功就行了。

所以一开始建图的时候要建一个正向的图,一个方向的图。

*/

#include<iostream>

#include<cstdio>

#include<vector>

#include<map>

#include<queue>

#include<cstring>

using namespace std;

#define MP make_pair

#define PB push_back

const int N=10005;

vector<int> mp[N],rv[N];

map< pair<int,int>,int > vis;

int f[N],p2i[N][N];

int dp[N*N][2];

int n,m;

struct Dt{

int v,turn;

Dt(){}

Dt(int _v,int _turn){ v=_v; turn=_turn; }

};

queue<Dt> que;

void init(){

int id=0;

for(int i=1;i<=n;++i)

for(int j=i;j<=n;++j)

p2i[j][i]=p2i[i][j]=id++;

for(int i=0;i<id;++i){

mp[i].clear();

rv[i].clear();

}

vis.clear();

for(int i=0;i<id;++i){

dp[i][0]=dp[i][1]=0;

}

}

int main(){

int T;

scanf("%d",&T);

while(T--){

scanf("%d%d",&n,&m);

init();

for(int i=0;i<m;++i){

for(int j=1;j<=n;++j)

scanf("%d",&f[j]);

for(int j=1;j<=n;++j)

for(int k=j+1;k<=n;++k){

int fr=p2i[j][k];

int to=p2i[f[j]][f[k]];

if(vis[MP(fr,to)]==0){

mp[fr].PB(to);

rv[to].PB(fr);

vis[MP(fr,to)]=1;

}

}

}

for(int i=1;i<=n;++i){

que.push(Dt(p2i[i][i],0));

que.push(Dt(p2i[i][i],1));

dp[p2i[i][i]][0]=dp[p2i[i][i]][1]=1;

}

while(!que.empty()){

Dt now=que.front();

que.pop();

if(now.turn==0){

int to=now.v;

for(int i=0;i<rv[to].size();++i){

int fr=rv[to][i];

if(dp[fr][1]==0){

int st=1;

for(int i=0;i<mp[fr].size();++i)

st&=dp[mp[fr][i]][0];

dp[fr][1]=st;

if(dp[fr][1])

que.push(Dt(fr,1));

}

}

}

else{

int to=now.v;

for(int i=0;i<rv[to].size();++i){

int fr=rv[to][i];

if(dp[fr][0]==0){

dp[fr][0]=1;

que.push(Dt(fr,0));

}

}

}

}

int ans=1;

for(int i=1;i<=n;++i){

for(int j=i;j<=n;++j){

ans&=dp[p2i[i][j]][0];

}

}

if(ans) puts("YES");

else puts("NO");

}

return 0;

}

时间: 2024-08-08 21:30:12

hdu 5165 Funny Game (博弈)的相关文章

hdu 2188 巴什博弈

巴什博奕(Bash Game):只有一堆n个物品,两个人轮流从这堆物品中取物,规 定每次至少取一个,最多取m个.最后取光者得胜. 显然,如果n=m+1,那么由于一次最多只能取m个,所以,无论先取者拿走多少个, 后取者都能够一次拿走剩余的物品,后者取胜.因此我们发现了如何取胜的法则:如果 n=(m+1)r+s,(r为任意自然数,s≤m),那么先取者要拿走s个物品,如果后取者拿走 k(≤m)个,那么先取者再拿走m+1-k个,结果剩下(m+1)(r-1)个,以后保持这样的 取法,那么先取者肯定获胜.总

HDU 2147-kiki&#39;s game(博弈/找规律)

kiki's game Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 40000/10000 K (Java/Others) Total Submission(s): 9174    Accepted Submission(s): 5485 Problem Description Recently kiki has nothing to do. While she is bored, an idea appears in his

HDU 3544 (不平等博弈) Alice&#39;s Game

切巧克力的游戏,想得还是不是太明白. 后者会尽量选前着切后其中小的一块来切,那么先手须尽量取中间来切. So?题解都是这么一句话,不知道是真懂了还是从别人那抄过来的. 后来找到一个官方题解,分析得比较认真,但我这智商还是没懂太多,QAQ 本题我抄袭自<Winning Ways for your Mathematical Plays> ,一本关于游戏论的科普类图书.这题是一个组合游戏,但是并不是一个对等的组合游戏,所以试图使用 SG 函数相关知识解答是会面临巨大的挑战的. 书中本题的做法描述得十

hdu 2897(巴什博弈变形)

邂逅明下 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4069    Accepted Submission(s): 1872 Problem Description 当日遇到月,于是有了明.当我遇到了你,便成了侣.那天,日月相会,我见到了你.而且,大地失去了光辉,你我是否成侣?这注定是个凄美的故事.(以上是废话)小 t和所有世俗的人

HDU 2177——威佐夫博弈

题目: Description 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同数量的石子.最后把石子全部取完者为胜者.现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者.如果你胜,你第1次怎样取子? Input 输入包含若干行,表示若干种石子的初始情况,其中每一行包含两个非负整数a和b,表示两堆石子的数目,a和b都不大于1,000,000,

HDU 2149————巴什博弈

Description 虽然不想,但是现实总归是现实,Lele始终没有逃过退学的命运,因为他没有拿到奖学金.现在等待他的,就是像FarmJohn一样的农田生涯. 要种田得有田才行,Lele听说街上正在举行一场别开生面的拍卖会,拍卖的物品正好就是一块20亩的田地.于是,Lele带上他的全部积蓄,冲往拍卖会. 后来发现,整个拍卖会只有Lele和他的死对头Yueyue. 通过打听,Lele知道这场拍卖的规则是这样的:刚开始底价为0,两个人轮流开始加价,不过每次加价的幅度要在1-N之间,当价格大于或等于

hdu 1907 尼姆博弈

John Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 3745    Accepted Submission(s): 2116 Problem Description Little John is playing very funny game with his younger brother. There is one big bo

HDU 1907 John(博弈)

题目 参考了博客:http://blog.csdn.net/akof1314/article/details/4447709 //0 1 -2 //1 1 -1 //0 2 -1 //1 2 -1 //2 2 -2 //0 3 -1 //1 3 -1 //2 3 -1 //3 3 -2 //0 4 -1 //1 4 -1 //2 4 -1 //3 4 -1 //4 4 -2 //0 5 -1 //1 5 -1 //2 5 -1 //3 5 -1 /* 尼姆博弈.对于N堆的糖,一种情况下是每堆都是

HDU 2147--HDU 2147(博弈)--我可能做了假题。。。

kiki's game Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 40000/1000 K (Java/Others) Total Submission(s): 238 Accepted Submission(s): 41 Problem Description Recently kiki has nothing to do. While she is bored, an idea appears in his mind, she