题意好懂不多说。这题有两种解法,一是网络流,二是状压
这题用状压做要将行压缩,那么就可以按行dp
状态方程:dp[i][j] 第i行状态为j时候的最大值
dp[nowst][j] = max(dp[nowst][j], dp[prest][k] + ans[j]);
分析会发现可以打表把所有状态离散化,因为很多状态是没用的,不过也可以每次都按照数据范围离散化,一个预处理时,一个是要用时。
#include<iostream> #include<algorithm> #include<stdlib.h> #include<string.h> #include<stdio.h> #include<math.h> #include<string> #include<vector> #include<queue> #include<list> using namespace std; #define ep 1e-9 #define oo 0x3f3f3f3f typedef __int64 lld; const lld mod = 1e9 + 7; int dp[2][(1 << 20) + 1]; int ans[1 << 20 + 1]; int map[21][21]; int now[(1 << 20) + 1], pre[(1 << 20) + 1]; int now_size, pre_size, n; void dfs(int row, int col, int st, int sum) { if (col > n) { ++now_size; now[now_size] = st; ans[now_size] = sum; return; } dfs(row, col + 2, st | (1 << (col - 1)), sum + map[row][col]); dfs(row, col + 1, st, sum); } int Dp() { memset(dp, 0, sizeof dp); int Max, nowst, prest; dp[0][1] = 0; pre[1] = 0; pre_size = 1; for (int i = 1; i <= n; i++) { prest = (i - 1) % 2; nowst = i % 2; now_size = 0; dfs(i, 1, 0, 0); for (int j = 1; j <= now_size; j++) dp[nowst][j] = 0; for (int j = 1; j <= now_size; j++) for (int k = 1; k <= pre_size; k++) { if (now[j] & pre[k]) continue; dp[nowst][j] = max(dp[nowst][j], dp[prest][k] + ans[j]); } memcpy(pre, now, sizeof pre); pre_size = now_size; } nowst = n % 2; Max = 0; for (int i = 1; i <= now_size; i++) Max = max(Max, dp[nowst][i]); return Max; } int main() { while (scanf("%d", &n) != EOF) { if (n == 0) { printf("0\n"); continue; } for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) scanf("%d", &map[i][j]); printf("%d\n", Dp()); } return 0; } /* */