“盛大遊戲杯”第15屆上海大學程序設計聯賽夏季賽暨上海高校金馬五校賽 I
阿新 • • 發佈:2017-07-14
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