您的位置:首页 > 其它

[状态压缩 dp] [CEOI 2002] Bugs Integrated, Inc.

2012-11-15 20:44 302 查看
Description
Bugs 公司是一个生产芯片的公司。他们在生产 6T 的 Q-RAM 芯片。每个芯片包含 6 个单位正方形,形成一个 2*3 的矩形。现在有一块一个 n*m 的矩形单晶硅,上面所有的格子都被测试过,坏的标记为黑色。最后,这块 n*m 的单晶硅要切出许多 2*3 的芯片。当然,任意一个芯片不能包括坏的格子。有可能不存在一种切法使得所有的好的格子都是芯片的一部分。公司想要尽量少的浪费。所以他们想知道这块单晶硅最多能切出多少个芯片。Input第一行包括一个整数 D 表示测试组数。对于每组测试数据,第一行三个整数 n、m、k (1 <= n <= 150, 1 <= m <= 10, 0 <= k <= nm)。k 表示坏的格子的数目。接下来 k 行,每行两个数 x、y 表示坏的格子的坐标。1 <= x <= n,1 <= y <= m。Output对于最组测试数据,输出最多能切出多少个芯片。
这一看就是一个状压 dp 对吧。不过貌似需要压两行,因为所放的芯片影响范围有三行(按行转移)。
状态就是 f[i][j][k], 表示第 i 行状态为 j,第 i + 1 行状态为 k 的最大值。然后按行转即可。
其实重点是一个小优化(但是有很大的作用):
在原来做广场铺砖之类的题目按行转移时,总是要把所有的状态 for 一遍。既然在这里压了两行,则 for 一遍要 1000000 次,这显然会非常慢。显然只需要保存有用的状态即可,所以用一个栈保存,速度翻了 4 倍多。
Code :
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
using namespace std;

typedef const int & intr;

struct pairy
{
int s, t;
pairy() {s = t = 0;}
pairy(intr x, intr y) {s = x, t = y;}
}	sta1[100000], sta2[100000], * s1 = sta1, * s2 = sta2, * tot, * up;

int T, n, m, k, lim, l, ans, tt, kk;
int ff[2][1024][1024];
int gg[2][1024][1024];
int (* f)[1024], (* f1)[1024];
int (* g)[1024], (* g1)[1024];
bool b[151][11];

void show(int a)
{
for (int i = 1; i <= m; ++ i)
if (a) fprintf(stderr, "%d", a & 1), a >>= 1;
else fputs("0", stderr);
fputs("\n", stderr);
}

bool chk1(intr x, intr y, intr z, intr p)
{
if (l + 2 > n || p + 1 > m) return 0;
for (int i = p; i < p + 2; ++ i)
if (x >> i - 1 & 1 || y >> i - 1 & 1 || z >> i - 1 & 1 || b[l][i] || b[l + 1][i] || b[l + 2][i]) return 0;
return 1;
}

bool chk2(intr x, intr y, intr p)
{
if (p + 2 > m) return 0;
for (int i = p; i < p + 3; ++ i)
if (x >> i - 1 & 1 || y >> i - 1 & 1 || b[l][i] || b[l + 1][i]) return 0;
return 1;
}

void dfs(int x, int y, int z, int p, int s)
{
if (p > m)
{
if (g[y][z] != tt + 1) f[y][z] = 0, g[y][z] = tt + 1, * (++ tot) = pairy(y, z);
ans = max(ans, f[y][z] = max(f[y][z], kk + s));
return;
}
if (chk1(x, y, z, p))
dfs(x | 3 << p - 1, y | 3 << p - 1, z | 3 << p - 1, p + 2, s + 1);
if (chk2(x, y, p))
dfs(x | 7 << p - 1, y | 7 << p - 1, z, p + 3, s + 1);
for (++ p; (x >> p - 1 & 1 || b[l][p]) && p <= m; ++ p);
dfs(x, y, z, p, s);
}

int main()
{
freopen("bugs.in", "r", stdin);
freopen("bugs.out", "w", stdout);

for (scanf("%d", & T); T --; )
{
scanf("%d%d%d", & n, & m, & k), lim = 1 << m;
memset(b, ans = 0, sizeof b);
for (int i = 1, x, y; i <= k; ++ i) scanf("%d%d", & x, & y), b[x][y] = 1;
g1 = gg[0], g = gg[1], f1 = ff[0], f = ff[1];
g1[0][0] = ++ tt, f1[0][0] = 0, tot = s1, * (++ tot) = pairy(0, 0);
for (l = 1; l < n; ++ l)
{
swap(s1, s2), up = tot, tot = s1;
for (pairy * i = s2 + 1; i <= up; ++ i)
kk = f1[i->s][i->t], dfs(i->s, i->t, 0, 1, 0);
swap(g1, g), swap(f1, f), ++ tt;
}
printf("%d\n", ans);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: