題目連結:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=77
類型: 雜湊判重 + 類比
原題:
The game of Spot is played on an NxN board as shown below for N = 4. During the game, alternate players may either place a black counter (spot) in an empty square or remove one from the board, thus producing
a variety of patterns. If a board pattern (or its rotation by 90 degrees or 180 degrees) is repeated during a game, the player producing that pattern loses and the other player wins. The game terminates in a draw after 2N moves if no duplicate pattern is produced
before then.
Consider the following patterns:
If the first pattern had been produced earlier, then any of the following three patterns (plus one other not shown) would terminate the game, whereas the last one would not.
Input and Output
Input will consist of a series of games, each consisting of the size of the board, N (2 N 50)
followed, on separate lines, by 2N moves, whether they are all necessary or not. Each move will consist of the coordinates of a square (integers in the range 1..N) followed by a blank and a character `+' or `-' indicating the addition or removal of a spot
respectively. You may assume that all moves are legal, that is there will never be an attempt to place a spot on an occupied square, nor to remove a non-existent spot. Input will be terminated by a zero (0).
Output will consist of one line for each game indicating which player won and on which move, or that the game ended in a draw.
Sample input
21 1 +2 2 +2 2 -1 2 +21 1 +2 2 +1 2 +2 2 -0
Sample output
Player 2 wins on move 3Draw
題目大意:
有一個在N*N棋盤上玩的遊戲叫做Spot, 它由兩個玩家輪流在棋盤上放置棋子或移除棋子, 一旦其中一個玩家放置或者移除棋子之後,那個棋盤的擺放狀態或者這個轉檯旋轉90度,180度是之前是出現過的,那麼他就輸了。
分析與總結:
看了下我做這題的提交記錄, 一共WA了17次
到底是什麼原因使得這並不難題的一題讓我WA得徹底噁心了?讓我們走近科學。
讓我WA的原因:
1. 棋盤並不是4*4的,而是N*N的。 WA了n次。
2. 旋轉問題。 題目其實說得有點含糊,只是說旋轉90度和180度。 我就以為共有4種狀態要判斷之前是否出現過,但是題目上又說了 (plus one other not shown) ,也就是說其實還有一個狀態沒有給出映像。 還有一個是什麼呢? 於是把題目給的映像通過旋轉函數列印了出來,
發現最後一副圖是不一樣的,通過旋轉方向根本就得不到。 這幅圖實際上是第一個的鏡面反射的圖。 所以題目說的還有一個沒有顯示出來的,是旋轉180度的那個映像。 因為這個原因又WA了n次。
這樣的錯誤說明我讀題還是太浮躁了,沉不下心來好好讀懂題意,看了個大概知道了原理和思路就直接做了,以後一定要改掉這個習慣。
糾正了這兩個錯誤後, 成功AC。
/* * UVa 141 - The Spot Game * Time: 0.044s (UVa) * Author: D_Double * */#include<iostream>#include<cstdio>#include<cstring>using namespace std;typedef int State[52][52];State board, que[105];const int HashSize = (1<<16);int N, nState, flag, head[HashSize], next[HashSize];// 類比得出旋轉後的狀態inline void rotate(State &next, State &s, int dir){ if(!dir) return; if(dir==1){ // 順時針90度 for(int i=0, x=0; i<N; ++i, ++x){ for(int j=N-1, y=0; j>=0; --j, ++y) next[x][y] = s[j][i]; } } else if(dir==2){ // 逆時針90度 for(int i=N-1, x=0; i>=0; --i, ++x){ for(int j=0, y=0; j<N; ++j, ++y) next[x][y] = s[j][i]; } } else if(dir==3){ // 180度 for(int i=N-1, x=0; i>=0; --i, ++x){ for(int j=N-1, y=0; j>=0; --j, ++y ) next[x][y] = s[i][j]; } } else if(dir==4){ // 鏡面反射 for(int i=0, x=0; i<N; ++i, ++x){ for(int j=N-1, y=0; j>=0; --j, ++y) next[x][y] = s[i][j]; } }}inline int hash(State &s){ int v=0; for(int i=0; i<N; ++i) for(int j=0; j<N; ++j) v = ((v<<1)+s[i][j]) % HashSize; return v%HashSize;}int search(State &s){ int h=hash(s); int u=head[h]; while(u){ if(memcmp(que[u], s, sizeof(s))==0) return 1; u = next[u]; } return 0;}inline void insert(int s){ int h=hash(que[s]); int u=head[h]; while(u){ u = next[u]; } next[s] = head[h] ; head[h] = s;} bool add_hash(int s){ State state[5]; memcpy(state[0], que[s], sizeof(que[s])); for(int i=0; i<=4; ++i){ rotate(state[i], que[s], i); if(search(state[i])) return false; } insert(s); return true;}inline void init(){ nState = 2; memset(head, 0, sizeof(head)); memset(board, 0, sizeof(board)); memcpy(que[1], board, sizeof(board)); insert(1); flag=0;}int main(){ int a, b, winner, step; char ch; while(scanf("%d", &N), N){ init(); for(int i=0; i<2*N; ++i){ scanf("%d %d %c",&a,&b,&ch); if(ch=='+') board[a-1][b-1] = 1; else board[a-1][b-1] = 0; memcpy(que[nState], board, sizeof(board)); if(!flag && !add_hash(nState)){ winner = !(i&1); step = i+1; flag=1; } ++nState; } if(flag) printf("Player %d wins on move %d\n", winner+1, step); else printf("Draw\n"); } return 0;}
—— 生命的意義,在於賦予它意義。
原創 http://blog.csdn.net/shuangde800 , By D_Double (轉載請標明)