1. 程式人生 > >“盛大遊戲杯”第15屆上海大學程序設計聯賽夏季賽暨上海高校金馬五校賽 I

“盛大遊戲杯”第15屆上海大學程序設計聯賽夏季賽暨上海高校金馬五校賽 I

mat tail for 我們 大學 一行 ace 一個 ostream

有一天,空和白很無聊,決定玩盛大遊戲,考慮到兩個人玩,他們隨便掏了一個遊戲出來:在一個n?m 的棋盤上,首先把史蒂芬妮·多拉放在左上角(1,1) 的位置。每次一個人可以將她往下,往右,往右下丟一格。當前回合,誰不能丟史蒂芬妮,誰就輸了。(註意,不可以把活人丟出棋盤啦!)遊戲總是空先手。

白說,這是一個垃圾遊戲!我們每次把史蒂芬妮丟素數個位置吧!(換句話說,每次丟2 3 5 7 或…格)空答應了。

我們都知道,空和白都很聰明,不管哪方存在一個可以必勝的最優策略,都會按照最優策略保證勝利。

玩了一局,空已經知道了這個遊戲的套路,現在他決定考考你,對於給定的n m ,空是贏是輸?如果空必勝,輸出“Sora”(無引號);反之,輸出“Shiro”(無引號)。

第一行有一個T表示數組組數,1<=T<100000
從第二行開始,每行為棋盤大小,n m 分別表示行列。
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\n"); 49 }else{ 50 printf("Sora\n"); 51 } 52 } 53 return 0; 54 }

“盛大遊戲杯”第15屆上海大學程序設計聯賽夏季賽暨上海高校金馬五校賽 I