BZOJ3438 小M的作物
20150302

BZOJ1187 [HNOI2007]神奇游乐园

laekov posted @ 2015年3月02日 23:22 in 未分类 with tags DP bzoj plugDP , 613 阅读

我的第二道插头DP。差不多纠结了一天。

 

这道题网上的题解都讲的好简略啊。最后还得自己yy。没有用括号序列法让我觉得自己比较厉害。

 

考虑轮廓线上的m个格子,有3种情况:没有插头,有且只能往一边走,有且要往两边走。对于第二种,要用最多3个不同的值来记录连通性。还要有两个不同的值来表示第一种情况和第三种情况。我比较懒,所以直接用一个八进制数去表示,然后每次二分找编号。

 

考虑转移,分一堆情况进行讨论。默认从左上朝右下走。

 

首先是要走当前格子的情况。

 

如果左边和上面都有插头,那么看它们是否连通。如果不连通则把它们连通,如果已经连通,看是否还有其它插头。没有就更新答案,否则忽略。

 

如果只有左边有插头,再分类。如果它是第二种,那么这个格子可以新建一个第三种插头,或者把左边格子的插头接过来。如果它是第三种那么它必需把左边格子接过来。

 

如果只有上面有插头,那么必需把上面的插头接上来。

 

如果左边和上面都没有插头,那么可以新建一个第三种插头。

 

然后如果不走这个格子的话,要求上面没有插头,且左边不是第三种插头。

 

按mhy的话说,插头dp就是写起来很麻烦。的确。不过写出来也还是挺高兴的。

 

然后代码丑到不能看了。

 

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 109;
const int maxm = 9;
const int maxst = 50009;
const int inf = 0x3f3f3f3f;

#define pow8(_x_) (1<<(_x_)<<(_x_)<<(_x_))
#define mbit(_x_,_y_) ((_x_)<<(_y_)<<(_y_)<<(_y_))
#define gbit(_x_,_y_) (((_x_)>>(_y_)>>(_y_)>>(_y_))&7)

int f[2][maxst], n, m, a[maxn][maxm], ans;
int slst[maxst], tots;

inline void upMax(int& a, int b) {
	if (a < b)
		a = b;
}

void dfsState(int cur, int tot, int val, int e) {
	if (cur == m) {
		static int cnt[maxm];
		memset(cnt, 0, sizeof(cnt));
		for (int i = 0; i < m; ++ i)
			++ cnt[gbit(val, i)];
		bool lg(1);
		for (int i = 1; i <= tot && lg; ++ i)
			if (cnt[i] != 0 && cnt[i] != 2)
				lg = 0;
		if (lg)
			slst[tots ++] = val;
	}
	else {
		for (int i = 0; i <= tot; ++ i)
			dfsState(cur + 1, tot, val | mbit(i, cur), e);
		dfsState(cur + 1, tot + 1, val | mbit(tot + 1, cur), e);
		if (e)
			dfsState(cur + 1, tot, val | mbit(7, cur), 0);
	}
}
void preState() {
	tots = 0;
	dfsState(0, 0, 0, 1);
	sort(slst, slst + tots);
}

int fState(int s) {
	int ret(lower_bound(slst, slst + tots, s) - slst);
	if (slst[ret] != s)
		puts("naive");
	return ret;
}

int joinState(int s, int p) {
	static int z[maxm], y[maxn], c;
	for (int i = 0; i < m; ++ i)
		z[i] = gbit(s, i);
	if (z[p - 1] == 7) {
		z[p - 1] = z[p];
		z[p] = 0;
	}
	else {
		int f(z[p]), t(z[p - 1]);
		for (int i = 0; i < m; ++ i)
			if (z[i] == f)
				z[i] = t;
		z[p - 1] = 0;
		z[p] = 0;
		memset(y, 0, sizeof(y));
		c = 0;
		for (int i = 0; i < m; ++ i)
			if (z[i] && z[i] < 7) {
				if (y[z[i]]) {
					z[i] = y[z[i]];
				}
				else {
					y[z[i]] = ++ c;
					z[i] = y[z[i]];
				}
			}
	}
	int f(0);
	for (int i = 0; i < m; ++ i)
		f |= mbit(z[i], i);
	return fState(f);
}

int expState(int s, int p) {
	static int z[maxm];
	for (int i = 0; i < m; ++ i)
		z[i] = gbit(s, i);
	int f(1);
	for (int i = 0; i < p - 1; ++ i)
		if (z[i] < 7 && z[i] + 1 > f)
			f = z[i] + 1;
	for (int i = 0; i < m; ++ i)
		if (z[i] < 7 && z[i] >= f)
			++ z[i];
	z[p - 1] = f;
	z[p] = f;
	f = 0;
	for (int i = 0; i < m; ++ i)
		f |= mbit(z[i], i);
	return fState(f);
}
int extState(int s, int p) {
	static int z[maxm];
	for (int i = 0; i < m; ++ i)
		z[i] = gbit(s, i);
	z[p] = z[p - 1];
	z[p - 1] = 0;
	int f(0);
	for (int i = 0; i < m; ++ i)
		f |= mbit(z[i], i);
	return fState(f);
}

int forkState(int s, int p) {
	return fState(s | mbit(7, p));
}

bool legalState(int s, int p) {
	static int z[maxm];
	for (int i = 0; i < m; ++ i)
		z[i] = gbit(s, i);
	for (int i = 0; i < p - 1; ++ i)
		if (z[i])
			return 0;
	for (int i = p + 1; i < m; ++ i)
		if (z[i])
			return 0;
	return 1;
}

void fillArr(int* a, int sz, int v) {
	for (int i = 0; i < sz; ++ i)
		a[i] = v;
}

void dp() {
	int cur(0), prv(1);
	fillArr(f[cur], tots, -inf);
	f[cur][0] = 0;
	for (int x = 0; x < n; ++ x) {
		for (int y = 0; y < m; ++ y) {
			swap(cur, prv);
			fillArr(f[cur], tots, -inf);
			f[cur][0] = 0;
			for (int i = 0; i < tots; ++ i) 
				if (f[prv][i] > -inf) {
					int s(slst[i]);
					if (gbit(s, y) && y && gbit(s, y - 1)) {
						if (gbit(s, y) == gbit(s, y - 1)) {
							if (legalState(s, y))
								upMax(ans, f[prv][i] + a[x][y]);
						}
						else {
							upMax(f[cur][joinState(s, y)], f[prv][i] + a[x][y]);
						}
					}
					if (!gbit(s, y) && y && gbit(s, y - 1)) {
						if (gbit(s, y - 1) == 7)
							upMax(f[cur][expState(s, y)], f[prv][i] + a[x][y]);
						else
							upMax(f[cur][extState(s, y)], f[prv][i] + a[x][y]);
					}
					if (gbit(s, y) && (!y || gbit(s, y - 1) != 7))
						upMax(f[cur][i], f[prv][i] + a[x][y]);
					if (y < m - 1 && !gbit(s, y) && (!y || gbit(s, y - 1) != 7))
						upMax(f[cur][forkState(s, y)], f[prv][i] + a[x][y]);
					if (!gbit(s, y) && (!y || gbit(s, y - 1) != 7))
						upMax(f[cur][i], f[prv][i]);
				}
		}
	}
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif

	scanf("%d%d", &n, &m);
	preState();
	ans = -inf;
	for (int i = 0; i < n; ++ i)
		for (int j = 0; j < m; ++ j)
			scanf("%d", a[i] + j);
	ans = -inf;
	dp();
	printf("%d\n", ans);
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter