BZOJ 2595: [Wc2008]游览计划 斯坦纳树
2016-09-02 10:33
295 查看
题意:连通n个景点的最小生成树(斯坦纳树)
用spfa转移dp方程,具体转移方式见hdu4085博文
此题还需要输出哪些边被用到了。这里记录一下每次转移的前继,最后从最优解开始,沿着前继边dfs,记录一下被访问到的边,最后按顺序输出被标记的边即可。
注:可以用三个数组记录前继,写起来更方便
c186
用spfa转移dp方程,具体转移方式见hdu4085博文
此题还需要输出哪些边被用到了。这里记录一下每次转移的前继,最后从最优解开始,沿着前继边dfs,记录一下被访问到的边,最后按顺序输出被标记的边即可。
注:可以用三个数组记录前继,写起来更方便
#include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> #include<math.h> #include<vector> #include<map> #define PIII pair< pair<int,int>, int> #define X first #define Y second #define MP make_pair #define ll long long #define mem(a, b) memset(a,b,sizeof(a)) using namespace std; const int maxn = 15; const int maxm = 1200; const int INF = 0x3f3f3f3f; const int maxq = maxn*maxn; int n, m, cnt, ma[maxn][maxn], dp[maxn][maxn][maxm], hd, tail; int q[maxq], vis[maxq]; int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; PIII pre[maxn][maxn][maxm]; void spfa(int s){ while(tail != hd){ int u = q[hd++], x = u/m+1, y = u%m+1; hd %= maxq, vis[u] = 0; for(int k = 0; k < 4; k ++){ int nx = x + dir[k][0], ny = y + dir[k][1], v = (nx-1)*m+ny-1; if(nx <= 0 || nx > n || ny <= 0 || ny > m) continue; if(dp[nx][ny][s] > dp[x][y][s] + ma[nx][ny]){ dp[nx][ny][s] = dp[x][y][s] + ma[nx][ny]; pre[nx][ny][s] = MP(MP(x, y), s); if(!vis[v]) q[tail++] = v, tail %= maxq, vis[v] = 1; } } } } void dfs(int i, int j, int k){ vis[(i-1)*m+j-1] = 1; if(pre[i][j][k].X.X == -1) return; dfs(pre[i][j][k].X.X,pre[i][j][k].X.Y,pre[i][j][k].Y); if(pre[i][j][k].X.X == i && pre[i][j][k].X.Y == j) dfs(pre[i][j][k].X.X,pre[i][j][k].X.Y, k ^ pre[i][j][k].Y); } int main(){ //freopen("input.txt", "r", stdin); scanf("%d%d", &n, &m); mem(dp, INF); for(int i = 1; i <= n; i ++) for(int j = 1; j <= m; j ++){ scanf("%d", &ma[i][j]); if(!ma[i][j]) dp[i][j][1<<cnt] = 0, cnt++; } for(int k = 1; k < (1<<cnt); k ++){ hd = tail = 0; for(int i = 1; i <= n; i ++) for(int j = 1; j <= m; j ++){ pre[i][j][k] = MP(MP(-1, -1), -1); for(int s = k; s; s = (s-1)&k){ if(dp[i][j][k] > dp[i][j][s] + dp[i][j][k-s] - ma[i][j]){ dp[i][j][k] = dp[i][j][s] + dp[i][j][k-s] - ma[i][j], pre[i][j][k] = MP(MP(i, j), s); } } if(dp[i][j][k] < INF) vis[(i-1)*m+j-1] = 1, q[tail++] = (i-1)*m+j-1, tail %= maxq; } spfa(k); } int ans = INF, x, y; for(int i = 1; i <= n; i ++) for(int j = 1; j<= m; j ++) if(dp[i][j][(1<<cnt)-1] < ans) ans = dp[i][j][(1<<cnt)-1], x = i, y = j; printf("%d\n", ans); mem(vis, 0); dfs(x, y, (1<<cnt)-1); for(int i = 1; i <= n; i ++){ for(int j = 1; j <= m; j ++){ if(!ma[i][j]) printf("x"); else if(vis[(i-1)*m+j-1]) printf("o"); else printf("_"); } printf("\n"); } return 0; }
c186
相关文章推荐
- 【BZOJ 2595】2595: [Wc2008]游览计划 (状压DP+spfa,斯坦纳树?)
- 【BZOJ2595】[Wc2008]游览计划 斯坦纳树
- BZOJ_2595_[Wc2008]游览计划_斯坦纳树
- 【bzoj2595】[Wc2008]游览计划 斯坦纳树
- BZOJ.2595.[WC2008]游览计划(DP 斯坦纳树)
- bzoj2595 [Wc2008]游览计划(最小斯坦纳树(状压DP))
- 斯坦纳树 [bzoj2595][wc2008]游览计划 题解
- BZOJ 2595 [Wc2008]游览计划 ——斯坦纳树
- BZOJ 2595 WC 2008 游览计划 斯坦纳树
- BZOJ 2595: [Wc2008]游览计划(斯坦纳树)
- bzoj 2595: [Wc2008]游览计划(斯坦纳树)
- 【BZOJ2595】【Wc2008】游览计划、斯坦纳树
- 【bzoj2595】[Wc2008]游览计划 斯坦纳树
- BZOJ 2595: [Wc2008]游览计划 [DP 状压 斯坦纳树 spfa]【学习笔记】
- [BZOJ2595][Wc2008]游览计划(斯坦纳树)
- [BZOJ]2595 [WC2008] 游览计划 斯坦纳树
- bzoj 2595 [Wc2008]游览计划(斯坦纳树)
- BZOJ 2595 Wc2008 游览计划 斯坦纳树
- BZOJ2595 Wc2008 游览计划
- BZOJ 2595 [Wc2008]游览计划