Luogu4363 [九省联考2018]一双木棋chess 【状压DP】【进制转换】
题目分析:
首先跑个暴力,求一下有多少种状态,发现只有18xxxx种,然后每个状态有10的转移,所以复杂度大约是200w,然后利用进制转换的技巧求一下每个状态的十进制码就行了。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int n,m; 5 6 int A[12][12],B[12][12]; 7 int kk[12][12]; // after number 8 9 int f[201000],arr[201000]; 10 11 int sit[12]; 12 13 int calc(){ 14 int ans = 0; 15 for(int i=1;i<=n;i++){ans += kk[i][sit[i]-1];} 16 return ans+1; 17 } 18 19 int dfs(int dr){ 20 int z = calc(); 21 if(arr[z]) return f[z]; 22 arr[z] = 1; f[z] = -1e9; 23 for(int i=1;i<=n;i++){ 24 if(sit[i] == m) continue; 25 if(i != 1 && sit[i] == sit[i-1]) continue; 26 sit[i]++; 27 f[z] = max(f[z],(dr==1?A[i][sit[i]]:B[i][sit[i]])-dfs(dr^1)); 28 sit[i]--; 29 } 30 return f[z]; 31 } 32 33 void read(){ 34 scanf("%d%d",&n,&m); 35 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&A[i][j]); 36 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&B[i][j]); 37 } 38 39 void work(){ 40 for(int i=1;i<=m;i++) kk[n+1][i] = 1; 41 for(int i=n;i>=1;i--){ 42 kk[i][0] = 1; 43 for(int j=1;j<=m;j++) kk[i][j] = kk[i][j-1]+kk[i+1][j]; 44 } 45 f[kk[1][m]] = 0; arr[kk[1][m]] = 1; 46 f[1] = dfs(1); 47 printf("%d\n",f[1]); 48 } 49 50 int main(){ 51 read(); 52 work(); 53 return 0; 54 }