hdu1565(状压dp)

题意好懂不多说。这题有两种解法,一是网络流,二是状压

这题用状压做要将行压缩,那么就可以按行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;
}
/*

*/


你可能感兴趣的:(dp,HDU)