BZOJ2402 陶陶的难题II
20150308 ur6

BZOJ1814 Ural 1519 Formula 1

laekov posted @ 2015年3月08日 17:02 in 未分类 with tags bzoj dp plugDP , 1261 阅读

插头dp的练手题么。虽然之前还没写过哈密顿回路的题。

 

学习了一下广义括号法。发现状态数比之前记连通性的方法要少。仔细想想发现,两个连通的插头的顺序有关。不能存在1212这种东西。所以连通性的方法记了很多废状态。那把连通性方法改进一下会不会变得更快呢?可以研究一下。我觉得应该是等效了吧。

 

今天的debug时间明显缩短了。虽然还是debug了老半天。然后怎么代码还是那么长。想起我每次都觉得把东西挤到一起看起来很不雅观,于是去写一堆找转移的函数。晕。

 

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

using namespace std;

typedef long long dint;
#ifdef WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif
#define _l (long long int)

const int maxn = 15;
const int maxst = 50009;

#define mbit(_x_,_y_) ((_x_)<<((_y_)<<1))
#define gbit(_x_,_y_) (((_x_)>>((_y_)<<1))&3)
#define cbit(_x_,_y_) ((_x_)&(~(3<<((_y_)<<1))))

int n, m, tots, slst[maxst];
bool mp[maxn][maxn];
dint f[2][maxst];

void dfsState(int l, int c, int z) {
	if (l == m + 1) {
		if (!c)
			slst[tots ++] = z;
	}
	else {
		dfsState(l + 1, c, z);
		dfsState(l + 1, c + 1, z | mbit(1, l));
		if (c)
			dfsState(l + 1, c - 1, z | mbit(2, l));
	}
}
void preState() {
	tots = 0;
	dfsState(0, 0, 0);
	sort(slst, slst + tots);
}
inline int fState(int s) {
	register int ret(lower_bound(slst, slst + tots, s) - slst);
	if (slst[ret] != s)
		puts("naive");
	return ret;
}

#define inc(_a_,_b_) (_a_+=_b_)
inline int brv(int x) {
	if (!x)
		return 0;
	else
		return (x == 1) ? 1 : -1;
}

bool isEnd(int s, int y) {
	for (int i = 0; i < y; ++ i)
		if (gbit(s, i))
			return 0;
	for (int i = y + 2; i <= m; ++ i)
		if (gbit(s, i))
			return 0;
	return 1;
}
inline int mergePlug(int s, int y) {
	int p, c;
	if (gbit(s, y) != gbit(s, y + 1)) {
		s = cbit(s, y);
		s = cbit(s, y + 1);
		return fState(s);
	}
	else if (gbit(s, y) == 1) {
		for (c = 1, p = y + 1; c; ++ p, c += brv(gbit(s, p)));
		s = cbit(s, y);
		s = cbit(s, y + 1);
		s = cbit(s, p);
		return fState(s | mbit(1, p));
	}
	else {
		for (c = -1, p = y; c; -- p, c += brv(gbit(s, p)));
		s = cbit(s, y);
		s = cbit(s, y + 1);
		s = cbit(s, p);
		return fState(s | mbit(2, p));
	}
}
inline int extPlugRight(int s, int y) {
	s |= mbit(gbit(s, y), y + 1);
	s = cbit(s, y);
	return fState(s);
}
inline int extPlugDown(int s, int y) {
	s |= mbit(gbit(s, y + 1), y);
	s = cbit(s, y + 1);
	return fState(s);
}
inline int forkPlug(int s, int y) {
	s |= mbit(1, y);
	s |= mbit(2, y + 1);
	return fState(s);
}
inline int nextRow(int s) {
	int r(0);
	for (int i = 0; i < m; ++ i)
		r |= mbit(gbit(s, i), i + 1);
	return fState(r);
}

dint dp() {
	int cur(0), prv(1);
	dint ans;
	memset(f, 0, sizeof(f));
	f[cur][0] = 1;
	for (int x = 0; x < n; ++ x) {
		for (int y = 0; y < m; ++ y) {
			if (mp[x][y])
				ans = 0;
			swap(cur, prv);
			memset(f[cur], 0, sizeof(f[cur]));
			for (int i = 0; i < tots; ++ i)
				if (f[prv][i]) {
					int s(slst[i]);;
					if (mp[x][y]) {
						if (gbit(s, y) && gbit(s, y + 1)) {
							if (gbit(s, y) == 1 && gbit(s, y + 1) == 2) {
								if (isEnd(s, y))
									inc(ans, f[prv][i]);
							}
							else
								inc(f[cur][mergePlug(s, y)], f[prv][i]);
						}
						else if (gbit(s, y)) {
							inc(f[cur][i], f[prv][i]);
							inc(f[cur][extPlugRight(s, y)], f[prv][i]);
						}
						else if (gbit(s, y + 1)) {
							inc(f[cur][i], f[prv][i]);
							inc(f[cur][extPlugDown(s, y)], f[prv][i]);
						}
						else
							inc(f[cur][forkPlug(s, y)], f[prv][i]);
					}
					else {
						if (!gbit(s, y) && !gbit(s, y + 1))
							inc(f[cur][i], f[prv][i]);
					}
				}
		}
		swap(cur, prv);
		memset(f[cur], 0, sizeof(f[cur]));
		for (int i = 0; i < tots; ++ i)
			if (f[prv][i] && !gbit(slst[i], m))
				inc(f[cur][nextRow(slst[i])], f[prv][i]);
	}
	return ans;
}

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

	scanf("%d%d", &n, &m);
	for (int i = 0; i < n; ++ i) {
		char g[maxn];
		scanf("%s", g);
		for (int j = 0; j < m; ++ j)
			mp[i][j] = (g[j] == '.');
	}
	preState();
	printf(lld "\n", dp());
}

登录 *


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