# bzoj2595 [Wc2008]游览计划

【题解】

（也就是枚举子集，因为(i,j)被多算了一次，所以要减掉）

（从周围四个格子转移过来，增加一个格子，如果是景点需要特别处理下s'）

【update】原来的板子。。这题能过但是其他题目好像跑的贼慢，更新了新板子

# include <queue>
# include <stdio.h>
# include <string.h>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 10 + 10, STATUS = 1027, N = 500010;
const int mod = 1e9+7;

# define RG register
# define ST static

int n, m, k = 0;
int mp[M][M], st[M][M];
int f[M][M][STATUS];
const int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};

struct pa {
int i, j, s;
pa() {}
pa(int i, int j, int s) : i(i), j(j), s(s) {}
inline int set() {
return i+11*j+11*11*s;
}
friend bool operator == (pa a, pa b) {
return a.i == b.i && a.j == b.j && a.s == b.s;
}
};

pa from[M][M][STATUS];
queue< pair<int,int> > q;
bool vis[M][M];
bool ans[M][M];

inline void spfa(int status) {
for (int i=1; i<=n; ++i)
for (int j=1; j<=m; ++j)
vis[i][j] = 1, q.push(make_pair(i, j));
while(!q.empty()) {
pair<int,int> top=q.front(); q.pop(); vis[top.first][top.second] = 0;
for (int i=0; i<4; ++i) {
int xx=top.first+dx[i], yy=top.second+dy[i];
if(xx<1||xx>n||yy<1||yy>m) continue;
if(f[xx][yy][status] > f[top.first][top.second][status] + mp[xx][yy]) {
f[xx][yy][status] = f[top.first][top.second][status] + mp[xx][yy];
from[xx][yy][status] = pa(top.first, top.second, status);
if(!vis[xx][yy]) {
vis[xx][yy] = 1;
q.push(make_pair(xx, yy));
}
}
}
}
}
inline void getans(int x, int y, int s) {
ans[x][y] = 1;
pa t = from[x][y][s];
if(t == pa(-1, -1, -1)) return ;
getans(t.i, t.j, t.s);
if(t.i==x && t.j==y) getans(t.i, t.j, s-t.s);
}

int main() {
for (int i=1; i<=10; ++i)
for (int j=1; j<=10; ++j)
for (int k=0; k<=1025; ++k) f[i][j][k] = 1e9, from[i][j][k] = pa(-1, -1, -1);
scanf("%d%d", &n, &m);
for (int i=1; i<=n; ++i)
for (int j=1; j<=m; ++j) {
f[i][j][0] = mp[i][j];
scanf("%d", &mp[i][j]);
if(mp[i][j] == 0)
f[i][j][1<<k] = 0, st[i][j] = (1<<k), ++k;
}
int status_size = (1<<k)-1;
for (int status=1; status<=status_size; ++status) {
for (int i=1; i<=n; ++i)
for (int j=1; j<=m; ++j) {
for (int ss = status-1&status; ss; ss=ss-1&status) {
if(f[i][j][status] > f[i][j][ss] + f[i][j][status^ss] - mp[i][j]) {
f[i][j][status] = f[i][j][ss] + f[i][j][status^ss] - mp[i][j];
from[i][j][status] = pa(i, j, ss);
}
}
}
spfa(status);
}

for (int i=1; i<=n; ++i)
for (int j=1; j<=m; ++j) {
if(!mp[i][j]) {
printf("%d\n", f[i][j][status_size]);
getans(i, j, status_size);
for (int x=1; x<=n; ++x, puts(""))
for (int y=1; y<=m; ++y)
if(ans[x][y]) {
if(mp[x][y]) printf("o");
else printf("x");
} else printf("_");
i = n+1, j = m+1;
}
}
return 0;
}
View Code

posted @ 2017-04-29 21:54  Galaxies  阅读(181)  评论(0编辑  收藏  举报