1. 程式人生 > >HDU 1565 方格取數(1)

HDU 1565 方格取數(1)

can getchar class target 方格取數 set ems n-k ++

鏈接

思路

  狀壓dp,dp[i][j]:表示到第i行,當前狀態為s的最大值。預處理在每一行選的時候可能的狀態,及這個狀態的價值。

  轉移方程:dp[i][j] = max(dp[i][j],dp[i-1][k]+sum[i][j]) k與j不沖突。

代碼

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 
 6 using namespace std;
 7 
 8 int sta[20010
],dp[22][20010],sum[22][20010],a[22][22]; 9 int n,tot; 10 11 12 inline int read() { 13 int x = 0,f = 1;char ch = getchar(); 14 for (; !isdigit(ch); ch=getchar()) if(ch==-) f=-1; 15 for (; isdigit(ch); ch=getchar()) x = x*10+ch-0; 16 return x * f; 17 } 18 void init() { 19 tot = 0
; 20 memset(dp,0,sizeof(dp)); 21 memset(sum,0,sizeof(sum)); 22 memset(sta,0,sizeof(sta)); 23 for (int i=1; i<=n; ++i) 24 for (int j=1; j<=n; ++j) 25 a[i][j] = read(); 26 27 } 28 void getsta() { 29 int t = (1 << n) - 1; 30 for (int i=0; i<=t; ++i) {
31 if (i & (i << 1) ) continue; 32 sta[++tot] = i; 33 } 34 } 35 void getsum() { 36 for (int i=1; i<=n; ++i) { 37 for (int j=1; j<=tot; ++j) { 38 for (int k=0; k<n; ++k) { 39 sum[i][j] += ((1<<k)&sta[j])?a[i][n-k]:0; 40 } 41 } 42 } 43 } 44 void getdp() { 45 for (int i=1; i<=tot; ++i) dp[1][i] = sum[1][i]; 46 for (int i=2; i<=n; ++i) { 47 for (int j=1; j<=tot; ++j) { 48 for (int k=1; k<=tot; ++k) { 49 if (sta[j] & sta[k]) continue; 50 dp[i][j] = max(dp[i][j],dp[i-1][k]+sum[i][j]); 51 } 52 } 53 } 54 } 55 void getans() { 56 int ans = 0; 57 for (int i=1; i<=tot; ++i) 58 ans = max(dp[n][i],ans); 59 cout << ans << "\n"; 60 } 61 int main() { 62 while (scanf("%d",&n) != EOF) { 63 init(); 64 getsta(); 65 getsum(); 66 getdp(); 67 getans(); 68 } 69 return 0; 70 }

HDU 1565 方格取數(1)