题意好懂不多说。这题有两种解法,一是网络流,二是状压
这题用状压做要将行压缩,那么就可以按行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;
}
/*
*/