这题刚开始理解错题意了 以为只能往右和下走
这题挺好的 看题解看了N久啊
二维的DP 第一维表示走到第几步 可以画一个正方形 以左上角斜着划线 第i步走的点只能是第i条线上的点 而dp的第二维 就表示的第i步可以到达的点的状态
另开一个a数组来表示 第i条线上每个字母的状态
dp所代表的值就为a与b的差值 以这个来进行选择 进行记忆化
确定下一步可以到达的字母的状态 是以当前可达的状态&下一步所要到达的字母的状态
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 using namespace std; 8 #define LL __int64 9 #define INF 1e9 10 int dp[42][1<<20],a[42][42]; 11 char s[22][22]; 12 int n; 13 int dfs(int step,int sta) 14 { 15 int i,num=0; 16 if(dp[step][sta]!=INF) 17 return dp[step][sta]; 18 for(i = 0; i < n ; i++) 19 { 20 if(sta&(1<<i)) 21 { 22 if(s[step-i][i]=='a') num++; 23 else if(s[step-i][i]=='b') num--; 24 break; 25 } 26 } 27 if(step==2*n-2) 28 return dp[step][sta] = num; 29 if(step%2!=0) 30 { 31 dp[step][sta] = -INF; 32 for(i = 0 ; i < 26 ; i++) 33 { 34 int next = a[step+1][i]&(sta|(sta<<1)); 35 if(next==0) 36 continue; 37 dp[step][sta] = max(dp[step][sta],dfs(step+1,next)+num); 38 } 39 return dp[step][sta]; 40 } 41 else 42 { 43 for(i = 0 ; i < 26 ; i++) 44 { 45 int next = a[step+1][i]&(sta|(sta<<1)); 46 if(next==0) 47 continue; 48 dp[step][sta] = min(dp[step][sta],dfs(step+1,next)+num); 49 } 50 return dp[step][sta]; 51 } 52 } 53 int main() 54 { 55 int i,j; 56 scanf("%d",&n); 57 for(i = 0 ; i < n ; i++) 58 cin>>s[i]; 59 for(i = 0 ; i < 2*n-1 ; i++) 60 { 61 for(j = 0 ; j < n ; j++) 62 { 63 if(i-j<0||i-j>=n) continue; 64 a[i][s[i-j][j]-'a'] |= (1<<j); 65 } 66 } 67 for(i = 0 ; i < 2*n ; i++) 68 for(j = 0 ; j < (1<<n) ; j++) 69 dp[i][j] = INF; 70 int ans = dfs(0,1); 71 if(ans>0) 72 puts("FIRST"); 73 else if(ans<0) 74 puts("SECOND"); 75 else 76 puts("DRAW"); 77 return 0; 78 }