1. 程式人生 > >Luogu4363 [九省聯考2018]一雙木棋chess 【狀壓DP】【進制轉換】

Luogu4363 [九省聯考2018]一雙木棋chess 【狀壓DP】【進制轉換】

\n number ace bsp con pac sin 狀壓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 }

Luogu4363 [九省聯考2018]一雙木棋chess 【狀壓DP】【進制轉換】