思路
状压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 << " "; 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 }