Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
解题思路初看题目木有什么思路,后来仔细看了下发现m>=6,这个是一个很关键的点。意味着我们需要求解的未放火柴只有12根,2^12 = 4096,这12根放与未放的情形只有4000多种,故可以采用状态DP。。。记忆化搜索一下。。详细见代码。 //By Lin #include<cstdio> #include<cstring> using namespace std; int m,mark[19],last[15],dp[5000][3]; const int triangle[19][5] = {{0,0,0,0,0},{1,2,3,0,0},{1,1,3,0,0},{2,1,2,5,7},{1,5,6,0,0},{2,4,6,3,7},{2,4,5,11,13}, {2,3,5,8,9},{1,7,9,0,0},{2,7,8,14,16},{1,11,12,0,0},{2,10,12,6,13},{1,10,11,0,0}, {2,6,11,14,15},{2,13,15,9,16},{1,13,14,0,0},{2,9,14,17,18},{1,16,18,0,0},{1,16,17,0,0}}; void swap(int &x ,int &y ) { int temp = x; x = y; y = temp; } int jisuan(int x , int y ) { if ( x>y ) swap(x ,y ); if ( y == x+1 && x != 1 ) { if ( x >=7 ) x -= 3; else if ( x>=4 ) x-=2; else x-=1; return x*3; } int t = x; if ( x >= 4 ) t+=3; else if ( x>=2 ) t+=2; else t+=1; int ret = (x-1)*3; ret += y>t?2:1; return ret; } void solve(int &x ,int &y ,int now ,int e ) { if ( e == 0 ) { x = 0; y = 0; return;} if ( dp[e][2] == 1 ) { x = dp[e][now]; y = dp[e][(now+1)%2]; return; } int k = 1,s[2]; dp[e][0] =-1; for (int o = 0; o<18-m; o++ , k *= 2 ) { if ( (k&e) == 0 ) continue; s[0] = s[1] = 0; int i = last[o]; mark[i] = 1; bool f = false; for (int j = 1; j<=triangle[i][0]; j++ ) if ( mark[triangle[i][j*2]] == 1 && mark[ triangle[i][j*2-1] ] == 1 ) { f = true; s[0]++; } int p ,q ; solve( p , q , f?0:1 , e ^ k ); s[0] += p; s[1] = q; if ( s[0] > dp[e][0] ) { dp[e][0] = s[0]; dp[e][1] = s[1]; } mark[i] = 0; } dp[e][2] = 1; x = dp[e][now]; y = dp[e][(now+1)%2]; return; } int main() { int cas,tt = 1; scanf("%d" , &cas ); while ( cas-- ) { int x, y,s[2],now,k; scanf("%d" , &m ); now = s[0] = s[1] = 0; memset( mark , 0 , sizeof(mark) ) ; for (int i = 0; i<m; i++ ) { scanf("%d%d" , &x,&y ); k = jisuan(x ,y ); bool f = false; for (int j = 1; j<=triangle[k][0]; j++ ) if ( mark[triangle[k][j*2]] == 1 && mark[ triangle[k][j*2-1] ] == 1 ) { f = true; s[now]++; } mark[k] = 1; if ( !f ) now = (now+1)%2; } k = 0; int e = 0; for (int i = 1; i<=18; i++) if ( mark[i] == 0 ) { last[k++] = i; e = e*2 + 1; } memset( dp, 0 , sizeof(dp) ); solve( x , y , now , e ); s[0] += x; s[1] += y; printf("Game %d: " , tt++ ); if ( s[0] > s[1] ) printf("A wins.\n"); else printf("B wins.\n"); } return 0; } Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator