hdu4539(状压dp)

题意:给出炮兵的打击范围,和一个矩阵,炮兵之间不能再对方的打击方位内,那么问矩阵最多可以放置多少个炮兵

状压,按照行dp,把行压缩,这题不能两行之间dp因为第一行会影响到第三行(炮兵的打击范围可以看出),那么就只能两行两行的dp

于是设计这样的状态:dp[i][now][pre] 在第i行时这行的状态为now上行的状态为pre时的最大值。

枚举这行的状态,上行的状态,上上行的状态,据处理将所有状态离散化,不然有些题目是会超时的。

#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;
int map[102][12];
int dp[2][(1 << 10) + 1][(1 << 10) + 1];
int st[(1 << 10) + 1];
int n, m, all;

void GetState()
{
	all = 0;
	for (int i = 0; i < (1 << 10);i++)
	if (!(i&(i << 2)))
		st[all++] = i;
}

int main()
{
	GetState();
	while (scanf("%d %d", &n, &m) != EOF)
	{
		for (int i = 1; i <= n; i++)
		for (int j = 0; j < m; j++)
			scanf("%d", &map[i][j]);
		memset(dp, 0, sizeof dp);
		int ans = 0;
		int nowall = 1 << m;
		for (int i = 1; i <= n; i++)
		for (int down = 0; down < all && st[down] < nowall; down++)
		{
			int sum = 0;
			for (int j = 0; j < m; j++)
			if (st[down] & (1 << j))
				sum += map[i][j];
			for (int cen = 0; cen < all&&st[cen] < nowall; cen++)
			if (!((st[down] << 1)&st[cen]) && !(st[down] & (st[cen] << 1)))
			{
				dp[i & 1][down][cen] = 0;
				for (int up = 0; up < all&&st[up] < nowall; up++)
				if (!(st[up] & st[down]) && !((st[cen] << 1)&st[up]) && !(st[cen] & (st[up] << 1)))
					dp[i & 1][down][cen] = max(dp[i & 1][down][cen], dp[(i - 1) & 1][cen][up]);
				dp[i & 1][down][cen] += sum;
				ans = max(dp[i & 1][down][cen], ans);
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}

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