HDU5754 多校联合3 人生赢家Bo
来源:互联网 发布:cs1.5弹道优化参数 编辑:程序博客网 时间:2024/05/21 22:24
题目连接:HDU5754
Life Winner Bo
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 574 Accepted Submission(s): 197
The size of the chessboard is
For each game,Bo and G take turns moving a chesspiece(Bo first).At first,the chesspiece is located at
In general,the chesspiece can only be moved right or down.Formally,suppose it is located at
Besides,There are four kinds of chess(They have movement rules respectively).
1.king.
2.rook(castle).
3.knight.
4.queen.
(The movement rule is as same as the chess.)
For each type of chess,you should find out that who will win the game if they both play in an optimal strategy.
Print the winner's name("B" or "G") or "D" if nobody wins the game.
In the next
"type" means the kind of the chess.
41 5 52 5 53 5 54 5 5
GGDB
题目分析:各种典型博弈论的杂粹。棋盘坐标按点算还是按格子算这个无所谓,看个人喜好了。没打过国际象棋还特意科普了一下规则。这里规定了只能严格的往右下走。国王只能走一格,横竖斜着都可以,如果只有横竖的话很好考虑,这个我们放到马一起写。车是横竖可走任意格,抽象一下就是典型的2堆的nim博弈(貌似?),反正取法就是两堆相等时后手必胜。第3个是马,马走的是日型与中国象棋一样。最后一个是王后,王后可以横竖斜着走任意格,同上抽象一下就是威佐夫博弈,直接套模板即可。
下面是马和国王的取法,这2个我是打表写的,首先国王,从终点开始,记为s2[0,0]=-1,B输记为-1,反之记为1,可知s2[1,0]=s[1,1]=s2[0,1]=1,然后每次角标和+1,每层遍历统计所有角标和为i的点下一步会到哪(3个点),如果这3个点有一个是必输的,那它这么走就肯定是必胜了。这3个点有一个是-1就出发点记为1,反之为-1,一层层统计完整个数组。到时候问起来直接查表就好了。
接下来是马。如果可以输可以僵局的话僵局是最优选择。官方题解上说画几个图找规律啥的,我在比赛时图快画烂了也没找到啥。最后还是打表做的。首先剪枝掉角标和不能被3整除的,这些显然会僵局,之后就是同国王了。s[0,0]=s[3,3]=-1,s[2,1]=s[1,2]=1,s[2,4]=s[4,2]=0,这里-1和1的意义同上,0代表僵局,之后的遍历过程也与上文相同。只是每个点有2种走法,看这2部走法有可以必胜的(对于上一个点是必输)就一定是必胜的点了,反之如果有可以僵局的点也可以避免必输,如果全是必输的那就只能是必输的点了。打表做法看似复杂度很高,但是棋盘只有1000*1000,总的计算量1000*1000*(2+3)=5百万很快的30ms,而且查询都是O(1)的操作。
PS:开始规则读错了规则,WA了一片,之后把打表范围取小了,直接WA到怀疑人生,最后看到AC的我终于可以把桌子砸掉了,,
#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;int s[1010][1010];int s2[1010][1010];void init(){ s[2][1]=s[1][2]=1; s[0][0]=s[3][3]=-1; s[4][2]=s[2][4]=0; for(int i=9;i<=2000;i+=3) { for(int j=2;2*j<=i;j++) { if(i-j>1000||j>1000) continue; int s1=-s[j-2][i-j-1]; int s2=-s[j-1][i-j-2]; s[j][i-j]=s[i-j][j]=max(s1,s2); } } memset(s2,-1,sizeof(s2)); s2[1][1]=s2[0][1]=s2[1][0]=1; for(int i=3;i<=2000;i++) { for(int j=1;2*j<=i;j++) { if(i-j>1000||j>1000) continue; int a1=-s2[j-1][i-j]; int a2=-s2[j][i-j-1]; int a3=-s2[j-1][i-j-1]; if(a1>0||a2>0||a3>0) s2[j][i-j]=s2[i-j][j]=1; else s2[j][i-j]=s2[i-j][j]=-1; } }}int main(){ int T,t,m,n; init(); cin>>T; while(T--) { cin>>t>>n>>m; int flag; if(t==1) { int buf=s2[n-1][m-1]; if(buf==-1)flag=0; else flag=1; } else if(t==2) { if(m==n) flag=0; else flag=1; } else if(t==3) { if((n+m-2)%3!=0) flag=2; else { int k=s[n-1][m-1]; if(k==-1) flag=0; if(k==0) flag=2; if(k==1) flag=1; } } else if(t==4) { n--;m--; int k = abs(n-m); n = n < m? n : m; int a_k= floor(k*(1.0 + sqrt(5.0))/2); if(n!=a_k) flag=1; else flag=0; } if(flag==0)cout<<"G"<<endl; if(flag==1)cout<<"B"<<endl; if(flag==2)cout<<"D"<<endl; }}
- HDU5754 多校联合3 人生赢家Bo
- 2016多校联赛3C (hdu5754) Life Winner Bo
- HDU5762 多校联合3 Teacher Bo
- hdu5754 多校3 Life Winner Bo【博弈】
- HDU5754 Life Winner Bo
- HDU 5761 多校联合 Rower BO
- hdu5754 Life Winner Bo 博弈
- 博弈--hdu5754 Life Winner Bo
- [HDU5756] Boss Bo [2016 Multi-University Training Contest 3(2016多校联合训练3) E]
- HDOJ 5752 (2016多校联合训练 Training Contest 3) Sqrt Bo
- HDOJ 5753 (2016多校联合训练 Training Contest 3) Permutation Bo
- HDOJ 5754 (2016多校联合训练 Training Contest 3) Life Winner Bo
- 2016多校联合第三场 HDU5758 Explorer Bo
- hdu5754 2016 Multi-University Training Contest 3 Life Winner Bo 解题报告
- hdu5754 Life Winner Bo (博弈混合)
- hdu5754 Life Winner Bo(博弈)
- hdu5754 Life Winner Bo 各种博弈(多校)
- hdu5754(2016多校第三场,博弈)
- UI基础_自定义非等高Cell_Xib封装_版本_有GIF_源代码
- framework service
- pdo 转utf8
- OpenJudge 百练 2016 ACM 暑期课练习题 Charm Bracelet
- [16-7-26]每日总结
- HDU5754 多校联合3 人生赢家Bo
- android studio contentprovider读取手机联系人
- listView滑动到底部和顶部
- 线程执行器
- audio framework学习 博客链接
- 设计模式总结2
- IO同步异步!
- PopupWindows 在指定控件上下左右显示
- HDU Problem 1896