sdoi 2009 & 状态压缩
是不是平时在手机里玩吃豆豆游戏玩腻了呢?最近MOKIA手机上推出了一种新的围豆豆游戏,大家一起来试一试吧。
游戏的规则非常简单,在一个N×M的矩阵方格内分布着D颗豆子,每颗豆有不同的分值Vi。游戏者可以选择任意一个方格作为起始格,每次移动可以随意的走到相邻的四个格子,直到最终又回到起始格。最终游戏者的得分为所有被路径围住的豆豆的分值总和减去游戏者移动的步数。矩阵中某些格子内设有障碍物,任何时刻游戏者不能进入包含障碍物或豆子的格子。游戏者可能的最低得分为0,即什么都不做。
注意路径包围的概念,即某一颗豆在路径所形成的多边形(可能是含自交的复杂多边形)的内部。下面有两个例子:
第一个例子中,豆在路径围成的矩形内部,所以豆被围住了。第二个例子中,虽然路径经过了豆的周围的8个格子,但是路径形成的多边形内部并不包含豆,所以没有围住豆子。
布布最近迷上了这款游戏,但是怎么玩都拿不了高分。聪明的你决定写一个程序来帮助他顺利通关。
SOL:
这题D=9,就算你不知道DP怎么写也知道这是撞鸭了,9,多么好的数字,2^9也不大.
撞鸭打的少,自己打的代码调的我想吐血.贴一发翁神的代码,既直观又美观,就算你从来不知道什么是撞鸭你也知道什么使撞鸭了....
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #define maxn 12 #define maxs 512 const int dx[] = {0, -1, 0, 1}; const int dy[] = {-1, 0, 1, 0}; using namespace std; int n, m, d, val[maxn], px[maxn], py[maxn], f[maxn][maxn][maxs]; int ans, nx, ny, ns, nw, up; bool v[maxn][maxn][maxs]; char map[maxn][maxn]; struct node{ int x, y, s; node(){} node(int _x, int _y, int _s){ x = _x; y = _y; s = _s;} }now; queue<node> q; void add(int x, int y, int s, int w) { v[x][y][s] = 1; f[x][y][s] = w; q.push(node(x, y, s)); } void solve(int sx, int sy) { memset(f, -0x3f, sizeof(f)); memset(v, 0, sizeof(v)); while (! q.empty()) q.pop(); add(sx, sy, 0, 0); while (! q.empty()){ now = q.front(); q.pop(); for (int i = 0; i < 4; ++ i){ nx = now.x + dx[i]; ny = now.y + dy[i]; if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && map[nx][ny] == '0'){ ns = now.s; nw = f[now.x][now.y][now.s] - 1; if (abs(dx[i]) == 1){ up = min(now.x, nx); for (int j = 1; j <= d; ++ j) if (px[j] == up && py[j] > ny){ ns ^= (1 << (j - 1)); if ((ns & (1 << (j - 1)))) nw += val[j]; else nw -= val[j]; } } if (! v[nx][ny][ns]) add(nx, ny, ns, nw); } } } for (int i = 0; i < (1 << d); ++ i) ans = max(ans, f[sx][sy][i]); } int main() { scanf("%d%d", &n, &m); scanf("%d", &d); for (int i = 1; i <= d; ++ i) scanf("%d", &val[i]); for (int i = 1; i <= n; ++ i){ scanf("%s", map[i] + 1); for (int j = 1; j <= m; ++ j) if (map[i][j] >= '1' && map[i][j] <= '9'){ px[map[i][j] - '0'] = i; py[map[i][j] - '0'] = j; } } for (int sx = 1; sx <= n; ++ sx) for (int sy = 1; sy <= n; ++ sy) if (map[sx][sy] == '0') solve(sx, sy); printf("%d\n", ans); return 0; }
Sometimes it s the very people who no one imagines anything of. who do the things that no one can imagine.