poj 4019 Immediate Delivery
来源:互联网 发布:monkey社交软件下载 编辑:程序博客网 时间:2024/06/09 09:06
dp。可以用spfa,也可以暴力一些的dp,我这里用的是暴力一些的dp。。。容易写一些。这道题的关键是输出路径,算是路径输出的好题吧!首先我们用dp[ i ][ j ]表示当前状态为 i (将点压缩) 时,最后访问的点为 j 时的最短距离,最后的答案就是两个除去第一个点的两个互补集合 i 和 ((1 << n) - 1 - i) | 1,的路程的和。然后先Floyd 预处理一下每两对点之间的距离,然后暴力枚举 状态,然后递推就可以了。输出路径比较恶心,需要将Floyd处理后的两点之间路径还原为原图上的路径,这样的话因为点比较少,我们直接暴力dfs搜索就可以了。详细看代码吧,路径输出那块儿实在是恶心。。。
#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<cstdio>#include<cmath>#define LL long long#define CLR(a, b) memset(a, b, sizeof(a))using namespace std;const int N = 20;const int M = 300000;const int INF = 0x3f3f3f3f;int G[N][N], dp[M][N], Len[M];int n, E[N][N], vis, pt[M][N], lpt[M];void Floyd(){ for(int k = 0; k < n; k ++) for(int i = 0; i < n; i ++) if(G[i][k] >= 0) for(int j = 0; j < n; j ++) if(G[k][j] >= 0 && (G[i][j] < 0 || G[i][j] > G[i][k] + G[k][j])) G[i][j] = G[i][k] + G[k][j];}int Solve(){ CLR(dp, -1);dp[1][0] = 0;CLR(Len, -1);CLR(pt, -1); for(int i = 0; i < (1 << n); i ++) for(int j = 0; j < n; j ++) if(dp[i][j] >= 0) { for(int k = 0; k < n; k ++) { if((1 << k) & i) continue; int tmp = i | (1 << k); if(dp[tmp][k] < 0 || dp[tmp][k] > dp[i][j] + G[j][k])//看这个转移状态应该很容易想到Spfa吧! dp[tmp][k] = dp[i][j] + G[j][k], pt[tmp][k] = j; } if(Len[i] < 0 || Len[i] > dp[i][j]) Len[i] = dp[i][j], lpt[i] = j; } int ret = INF; for(int i = 1; i < (1 << n); i ++) { int bt = (1 << n) - 1 - i, tmp = INF; if(Len[i] >= 0 && Len[bt | 1] >= 0) tmp = max(Len[i], Len[bt | 1]); if(tmp < ret) { ret = tmp; vis = i; } } return ret;}vector<int>path;bool dfs(int u, int v, int q, int len){ if(len > G[q][v]) return 0; if(u == v) { return len == G[q][v]; } for(int i = 0; i < n; i ++) { if(E[u][i] > 0 && E[u][i] <= G[q][v]) { if(dfs(i, v, q, len + E[u][i])) { path.push_back(u + 1); return 1; } } } return 0;}void find(int val, int u){ int v = pt[val][u]; if(v < 0) return; dfs(v, u, v, 0); find(val - (1 << u), v);}void Path(int val){ path.clear();path.push_back(lpt[val] + 1); find(val, lpt[val]); printf("%d", path.size() - 1); for(int i = path.size() - 1; i >= 0; i --) { printf(" %d", path[i]); }puts("");}int main(){ int m, u, v, c; while(scanf("%d%d", &n, &m) != EOF) { CLR(G, -1); for(int i = 0; i < m; i ++) { scanf("%d%d%d", &u, &v, &c); u --, v --;G[i][i] = 0; G[u][v] = G[v][u] = c; } memcpy(E, G, sizeof(E)); Floyd(); printf("%d\n", Solve()); Path(vis);vis = ((1 << n) - 1 - vis) | 1; Path(vis); }}
- poj 4019 Immediate Delivery
- poj 1695 Magazine Delivery
- poj 1695 Magazine Delivery
- poj 1695 Magazine Delivery
- poj 1056 : immediate decodability
- POJ 1056 IMMEDIATE DECODABILITY
- POJ 1056 IMMEDIATE DECODABILITY
- <poj 1056>IMMEDIATE DECODABILITY
- poj 1056 IMMEDIATE DECODABILITY
- poj 1056 IMMEDIATE DECODABILITY
- poj 1056 immediate decodability
- POJ 1056 IMMEDIATE DECODABILITY
- POJ IMMEDIATE DECODABILITY
- POJ 1056 IMMEDIATE DECODABILITY
- poj 1056 IMMEDIATE DECODABILITY
- POJ 1056 IMMEDIATE DECODABILITY
- POJ 1056 IMMEDIATE DECODABILITY
- IMMEDIATE DECODABILITY POJ
- java对象创建过程/初始化顺序
- 在左右相差为1数组中查找一个数
- C#中Invoke的用法(转)
- Linux Socket编程(不限Linux)
- Jquery 改变一个单个 属性和多个属性。
- poj 4019 Immediate Delivery
- java反射机制
- VC++ Sleep函数原理及Sleep(0)的使用(文章较深入但通俗易懂)
- 栈——表达式求值
- iOS7----64位与32位 对比 数据类型
- LA 3363 String Compression(dp)
- Android关于分辨率的支持(QVGA,HVGA,WVGA,WXGA)
- 数据库 三范式最简单最易记的解释
- 用Doxygen+Graphviz生成函数调用流程图