“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛 I

有一天,空和白很无聊,决定玩盛大游戏,考虑到两个人玩,他们随便掏了一个游戏出来:在一个n 的棋盘上,首先把史蒂芬妮·多拉放在左上角(1,1 的位置。每次一个人可以将她往下,往右,往右下丢一格。当前回合,谁不能丢史蒂芬妮,谁就输了。(注意,不可以把活人丢出棋盘啦!)游戏总是空先手。

白说,这是一个垃圾游戏!我们每次把史蒂芬妮丢素数个位置吧!(换句话说,每次丢 或…格)空答应了。

我们都知道,空和白都很聪明,不管哪方存在一个可以必胜的最优策略,都会按照最优策略保证胜利。

玩了一局,空已经知道了这个游戏的套路,现在他决定考考你,对于给定的 ,空是赢是输?如果空必胜,输出“Sora”(无引号);反之,输出“Shiro”(无引号)。

第一行有一个T表示数组组数,1<=T<100000 
从第二行开始,每行为棋盘大小, 分别表示行列。
1=<n<=500 1=<m<=500 

对于每组数据,按题目要求输出。

复制
4
1 1
2 2
10 10
30 30
Shiro
Shiro
Shiro
Sora

解法:
1 可以肯定,如果经过操作这个人可以到右下角,那一定是胜利的
2 n,m很小,我们把所有的情况dfs一次,也就是说对于每种棋盘都有一个记录位置(这里是谁走的)
3 每次dfs都用到上一次的棋盘记录,所以用dp记录下来(比如处理完1*1,再处理1*2,自然需要用1*1的值)
3 代码解释 每次返回都取反 如果上个位置为1,说明这次是0操作,0同理,然后求或,如果这次是1,那么一定有机会让这个位置最后保留为1,为0的情况只有0访问过
 1 #include <algorithm>
 2 #include <iostream>
 3 #include <string.h>
 4 #include <cstdio>
 5 #include <cmath>
 6 #define N 550
 7 #define LL long long
 8 using namespace std;
 9 int dp[N][N];
10 int n,m;
11 int Solve(int x){
12     for(int i=2;i*i<=x;i++){
13         if(x%i==0){
14             return 0;
15         }
16     }
17     return 1;
18 }
19 int flag[N][N];
20 vector<int>Ve;
21 int dfs(int x,int y){
22     if(flag[x][y]) return dp[x][y];
23     flag[x][y]=1;
24     for(int i=0;i<Ve.size();i++){
25         if(x-Ve[i]>0) dp[x][y]|=(!dfs(x-Ve[i],y));
26         if(y-Ve[i]>0) dp[x][y]|=(!dfs(x,y-Ve[i]));
27         if(x-Ve[i]>0&&y-Ve[i]>0) dp[x][y]|=(!dfs(x-Ve[i],y-Ve[i]));
28     }
29     return dp[x][y];
30 }
31 int main(){
32     for(int i=2;i<=510;i++){
33         if(Solve(i)){
34             Ve.push_back(i);
35         }
36     }
37     for(int i=1;i<=510;i++){
38             for(int j=i;j<=510;j++){
39                 dfs(i,j);
40             }
41         }
42     int t;
43     scanf("%d",&t);
44     while(t--){
45         int n,m;
46         scanf("%d%d",&n,&m);
47         if(dp[n][m]==0){
48             printf("Shiro
");
49         }else{
50             printf("Sora
");
51         }
52     }
53     return 0;
54 }
原文地址:https://www.cnblogs.com/yinghualuowu/p/7163789.html