最简单的博弈论——HDU - 5963 朋友 (博弈)

OK,好的先看一下题意:

B君在围观一群男生和一群女生玩游戏,具体来说游戏是这样的: 
给出一棵n个节点的树,这棵树的每条边有一个权值,这个权值只可能是0或1。 在一局游戏开始时,会确定一个节点作为根。接下来从女生开始,双方轮流进行 操作。 
当一方操作时,他们需要先选择一个不为根的点,满足该点到其父亲的边权为1; 然后找出这个点到根节点的简单路径,将路径上所有边的权值翻转(即0变成1,1 变成0 )。 
当一方无法操作时(即所有边的边权均为0),另一方就获得了胜利。 
如果在双方均采用最优策略的情况下,女生会获胜,则输出“Girls win!”,否则输 出“Boys win!”。 
为了让游戏更有趣味性,在每局之间可能会有修改边权的操作,而且每局游戏指 定的根节点也可能是不同的。 
具体来说,修改边权和进行游戏的操作一共有m个,具体如下: 
??“0 x”表示询问对于当前的树,如果以x为根节点开始游戏,哪方会获得胜利。 
??“1 x y z ”表示将x和y之间的边的边权修改为z。

—————————————————————————————————————————————————————————————————————————————

 sorry,代码在下面

题意应该比较好懂,一般人应该也知道这是博弈论。

但是我建议大家先模拟一下样例,方便理解。

但是具体怎么想呢?

博弈论一般都要先想什么时候是必胜状态。

同理:

这道题的必胜状态是什么呢?

当根节点所连的边中只有一条边的权值为1的话,那么肯定是 女生赢。

当根节点只连一条边,且边的权值是1,在这条边之后又连了很多条边,随便编的权值。

第一次女生翻转,那么第一条边的权值变成了0. 男生肯定不能翻转第一条边,

如果男生不能翻转,那么女生就赢了,如果男生还可以翻转,这时候第一条边又变成了1.

女生翻转又把第一条边变成了0.所以男生永远不可能翻转第一条边。

所以这种状态一定是女生赢。(根节点连了一条权值为1 的边。)

如果根节点连的边的权值和 为奇数,就是女生赢,反之就是男生赢。

是不是很简单。

然后是超级简单的代码。

提醒大家注意理解sum数组的含义。

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 const int maxn=40005;
 5 struct node{
 6     int from,to,next,value;
 7 }e[maxn<<1];
 8 int head[maxn],cnt,sum[maxn];
 9 void add(int x,int y,int z){
10     e[++cnt].from=x;e[cnt].to=y;e[cnt].value=z;e[cnt].next=head[x];head[x]=cnt;
11 }
12 int main(){
13     //freopen("a.in","r",stdin);
14     int t;scanf("%d",&t);
15     while(t--){
16         memset(e,0,sizeof(e));
17         memset(head,0,sizeof(head));
18         memset(sum,0,sizeof(sum));
19         cnt=0;
20         int n,m;scanf("%d%d",&n,&m);
21         for(int i=1;i<n;i++){
22             int x,y,z;scanf("%d%d%d",&x,&y,&z);
23             add(x,y,z);add(y,x,z);
24             sum[x]+=z;sum[y]+=z;
25         }
26         for(int i=1;i<=m;i++){
27             int u;scanf("%d",&u);
28             if(u==0){
29                 int x;scanf("%d",&x);
30                 int ans=sum[x];
31                 if(ans%2==1)printf("Girls win!\n");
32                 else printf("Boys win!\n");
33             }
34             else {
35                 int x,y,z;scanf("%d%d%d",&x,&y,&z);
36                 for(int k=head[x];k;k=e[k].next){
37                     int v=e[k].to;
38                     if(v==y){
39                         sum[x]-=e[k].value;
40                         sum[x]+=z;
41                         e[k].value=z;
42                     }
43                 }
44                 for(int k=head[y];k;k=e[k].next){
45                     int v=e[k].to;
46                     if(v==x){
47                         sum[y]-=e[k].value;
48                         sum[y]+=z;
49                         e[k].value=z;break;
50                     }
51                 }
52             }
53         }
54     }
55     return 0;
56 } 

原文地址:https://www.cnblogs.com/DZN2004/p/12685483.html

时间: 2024-10-13 15:31:33

最简单的博弈论——HDU - 5963 朋友 (博弈)的相关文章

HDU 5963 朋友 【博弈论】 (2016年中国大学生程序设计竞赛(合肥))

朋友 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description B君在围观一群男生和一群女生玩游戏,具体来说游戏是这样的:给出一棵n个节点的树,这棵树的每条边有一个权值,这个权值只可能是0或1. 在一局游戏开始时,会确定一个节点作为根.接下来从女生开始,双方轮流进行 操作.当一方操作时,他们需要先选择一个不为根的点,满足该点到其父亲的边权为1; 然

HDU 5963 朋友(找规律博弈)

http://acm.hdu.edu.cn/showproblem.php?pid=5963 题意: 思路: 我们可以先只考虑单链,自己试几种案例就可以发现规律,只有与根相连的边为1时,只需要奇数次操作,也就是1次就可以,而别的都需要偶数次操作才能把这条链上的边权全变成0,次数为$2^{n-1}$,n为边的层数.所以我们只要统计与根相连的有多少条权值为1的边即可. 需要改权值的时候搜索一下找到边然后修改. 1 #include<iostream> 2 #include<algorithm

hdu 5963 朋友(2016ccpc 合肥站 C题)

朋友 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 215    Accepted Submission(s): 137 Problem Description B君在围观一群男生和一群女生玩游戏,具体来说游戏是这样的:给出一棵n个节点的树,这棵树的每条边有一个权值,这个权值只可能是0或1. 在一局游戏开始时,会确定一个节点作为根.接下

hdu 5693 朋友 博弈

朋友 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description B君在围观一群男生和一群女生玩游戏,具体来说游戏是这样的:给出一棵n个节点的树,这棵树的每条边有一个权值,这个权值只可能是0或1. 在一局游戏开始时,会确定一个节点作为根.接下来从女生开始,双方轮流进行 操作.当一方操作时,他们需要先选择一个不为根的点,满足该点到其父亲的边权为1; 然

hdu 3032(博弈sg函数)

题意:与原来基本的尼姆博弈不同的是,可以将一堆石子分成两堆石子也算一步操作,其它的都是一样的. 分析:由于石子的堆数和每一堆石子的数量都很大,所以肯定不能用搜索去求sg函数,现在我们只能通过找规律的办法求得sg的规律. 通过打表找规律可以得到如下规律:if(x%4==0) sg[x]=x-1; if(x%4==1||x%4==2) sg[x]=x; if(x%4==3) sg[x] = x+1. 打表代码: #include<iostream> #include<cstdio> #

简单的dp hdu 数塔(水题)

数塔 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 21314    Accepted Submission(s): 12808 Problem Description 在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的: 有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少

HDU 5963 博弈

http://acm.hdu.edu.cn/showproblem.php?pid=5963 题目大意:中文题 思路:看ICPC camp好了,简单易懂:https://async.icpc-camp.org/d/628-2016     上面的C题 //看看会不会爆int!数组会不会少了一维! //取物问题一定要小心先手胜利的条件 #include <bits/stdc++.h> using namespace std; #pragma comment(linker,"/STACK

朋友HDU - 5963 (思维题) 三种方法

传送门 题目描述 输入 输出 样例输入 2 2 3 1 2 0 0 1 1 2 1 1 0 2 4 11 1 2 1 2 3 1 3 4 0 0 1 0 2 0 3 0 4 1 2 1 0 0 1 0 2 0 3 1 3 4 1 0 3 0 4 Sample Input 样例输出 Boys win! Girls win! Girls win! Boys win! Girls win! Boys win! Boys win! Girls win! Girls win! Boys win! Girl

hdu 1850 Being a Good Boy in Spring Festival 博弈论之尼姆博弈,,都被自己蠢哭了!

Being a Good Boy in Spring Festival Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5157    Accepted Submission(s): 3092 Problem Description 一年在外 父母时刻牵挂 春节回家 你能做几天好孩子吗 寒假里尝试做做下面的事情吧 陪妈妈逛一次菜场 悄悄