HDU 4571 Travel in time (SPFA 或 dp)
来源:互联网 发布:算法基础 豆瓣 编辑:程序博客网 时间:2024/06/13 04:47
HDU 4571
大概题意:n个点(<=100)m条边(<=1000)的无向图,每个点有消耗costp和价值moneyp,每条边有消耗coste。问从点s出发到点e,消耗不超过t(<=300)所获得的最大价值。经过边必有消耗coste;经过点时,当取得价值moneyp时消耗costp,即为visit该点;当取得价值0,时消耗也为0,即为pass该点。visit的点的moneyp值必须是严格升序。
解法:
容易看出应该用spfa和dp来解。关键时对visit和pass点的处理。
通过floyd预处理出visit每个点对之间的最小边消耗。然后,加一个超级源点和一个超级终点。超级源点负责pas点s能够到达的点,超级终点负责那些能越过e的点
由于visit的点的moneyp值必须严格升序所以也可以拓扑之后dp
不能用dij,因为本题时求最长路,且有正边。需用spfs
注意:
(1)spfa中跑的状态都是合理的,所以可以初始化dp为0;而dp中枚举的状态不一定是合理的,所以要初始化dp为-1
(2)spfa的两种写法,
先建图在跑spfa。
在跑spfa的过程中判断边。
坑点:本题卡vector,要用手写的链表或邻接矩阵
spfa:
//#pragma warning (disable: 4786)//#pragma comment (linker, "/STACK:16777216")//HEAD#include <cstdio>#include <ctime>#include <cstdlib>#include <cstring>#include <queue>#include <string>#include <set>#include <stack>#include <map>#include <cmath>#include <vector>#include <iostream>#include <algorithm>using namespace std;#define REP(i, N) for(int i = 0; i < (N); ++i)#define CLR(A,value) memset(A,value,sizeof(A))#define RI(n) scanf("%d", &n)#define RII(n, m) scanf("%d%d", &n, &m)#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)#define RS(s) scanf("%s", s)typedef long long LL;const int INF = 0x3f3f3f3f;const double eps = 1e-10;const int maxn = 111 * 310;int cost[111], money[111];int d[111][111];int dp[111][310];int inq[111][310];void floyed(int n){ REP(k, n) REP(i, n) REP(j, n) { d[i][j] = min(d[i][j], d[i][k] + d[k][j]); }}int n, m, t, s, e;int spfa(int ss, int ee){ queue<int>qu; queue<int>qct; memset(dp, 0, sizeof(dp)); memset(inq, 0, sizeof(inq)); qu.push(ss); qct.push(0); inq[ss][0] = 1; int ans = 0; while (!qu.empty()) { int u = qu.front(); qu.pop(); int uct = qct.front(); qct.pop(); inq[u][uct] = 0; if (u == ee) ans = max(ans, dp[u][uct]); for (int v = 0; v < n; v++) { if (v == u || (money[u] >= money[v] && v != ee)) continue; int vct = uct + d[u][v] + cost[v]; if (vct <= t && dp[v][vct] < dp[u][uct] + money[v]) { dp[v][vct] = dp[u][uct] + money[v]; if (!inq[v][vct]) { qu.push(v); qct.push(vct); inq[v][vct] = 1; } } } } return ans;}int main (){ int test; RI(test); int ncase = 1; while (test--) { scanf("%d%d%d%d%d", &n, &m, &t, &s, &e); memset(d, 0x3f, sizeof(d)); for (int i = 0; i < n; i++) RI(cost[i]); for (int i = 0; i < n; i++) RI(money[i]); for (int i = 0; i < n + 2; i++) d[i][i] = 0; for (int i = 0; i < m; i++) { int x, y, z; scanf("%d%d%d", &x, &y, &z); d[x][y] = min(d[x][y], z); d[y][x] = d[x][y]; } floyed(n); int ss = n; int ee = n + 1; cost[ss] = money[ss] = 0; cost[ee] = money[ee] = 0; for (int i = 0; i < n; i++) if (d[s][i] != INF) d[ss][i] = d[s][i]; for (int i = 0; i < n; i++) if (d[i][e] != INF) d[i][ee] = d[i][e]; d[ss][ee] = d[s][e]; n += 2; int ans = spfa(ss, ee); printf("Case #%d:\n", ncase++); printf("%d\n", ans); } return 0;}
另种,先建图在跑spfa:
//#pragma warning (disable: 4786)//#pragma comment (linker, "/STACK:16777216")//HEAD#include <cstdio>#include <ctime>#include <cstdlib>#include <cstring>#include <queue>#include <string>#include <set>#include <stack>#include <map>#include <cmath>#include <vector>#include <iostream>#include <algorithm>using namespace std;#define REP(i, N) for(int i = 0; i < (N); ++i)#define CLR(A,value) memset(A,value,sizeof(A))#define RI(n) scanf("%d", &n)#define RII(n, m) scanf("%d%d", &n, &m)#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)#define RS(s) scanf("%s", s)typedef long long LL;const int INF = 0x3f3f3f3f;const double eps = 1e-10;const int maxn = 111 * 310;struct Edge{ int from, to, dist;};struct BellmanFord { int n, m; int head[maxn]; int next[maxn * 110]; int to[maxn * 110]; int dist[maxn * 110]; int tot; bool inq[maxn]; int d[maxn]; void init(int n) { this->n = n; tot = 0; memset(head, -1, sizeof(head)); } void AddEdge(int ufrom, int uto, int udist) { to[tot] = uto; dist[tot] = udist; next[tot] = head[ufrom]; head[ufrom] = tot++; } bool spfa(int ss) { queue<int>Q; memset(inq, 0, sizeof(inq)); memset(d, 0, sizeof(d)); d[ss] = 0; inq[ss] = 1; Q.push(ss); while (!Q.empty()) { int u = Q.front(); Q.pop(); inq[u] = false; for (int i = head[u]; ~i; i = next[i])// for (int i = 0; i < G[u].size(); i++) { int uto = to[i]; int udist = dist[i];// Edge& e = edges[G[u][i]]; if (d[uto] < d[u] + udist) { d[uto] = d[u] + udist; if (!inq[uto]) { Q.push(uto); inq[uto] = true; } } } } return false; }}bm;int cost[111], money[111];int d[111][111];void floyed(int n){ REP(k, n) REP(i, n) REP(j, n) { d[i][j] = min(d[i][j], d[i][k] + d[k][j]); }}int n, m, t, s, e;int ID(int x, int y){ return x * (t + 1) + y;}int main (){ int test; RI(test); int ncase = 1; while (test--) { scanf("%d%d%d%d%d", &n, &m, &t, &s, &e); memset(d, 0x3f, sizeof(d)); for (int i = 0; i < n; i++) d[i][i] = 0; for (int i = 0; i < n; i++) RI(cost[i]); for (int i = 0; i < n; i++) RI(money[i]); for (int i = 0; i < m; i++) { int x, y, z; scanf("%d%d%d", &x, &y, &z); d[x][y] = min(d[x][y], z); d[y][x] = d[x][y]; } floyed(n); int ss = n * (t + 1); int ee = ss + 1; bm.init(ee + 1); for (int i = 0; i < n; i++) if (d[s][i] + cost[i] <= t) bm.AddEdge(ss, ID(i, d[s][i] + cost[i]), money[i]); bm.AddEdge(ss, ee, 0); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i == j || money[i] >= money[j] || d[i][j] == INF) continue; for (int tt = 0; tt + d[i][j] + cost[j] <= t; tt++) { bm.AddEdge(ID(i, tt), ID(j, tt + d[i][j] + cost[j]), money[j]); } } } for (int i = 0; i < n; i++) if (d[i][e] != INF) for (int tt = 0; tt + d[i][e] <= t; tt++) bm.AddEdge(ID(i, tt), ee, 0); bm.spfa(ss); int ans = bm.d[ee]; printf("Case #%d:\n", ncase++); printf("%d\n", ans); } return 0;}
先拓扑,在dp
//#pragma warning (disable: 4786)//#pragma comment (linker, "/STACK:16777216")//HEAD#include <cstdio>#include <ctime>#include <cstdlib>#include <cstring>#include <queue>#include <string>#include <set>#include <stack>#include <map>#include <cmath>#include <vector>#include <iostream>#include <algorithm>using namespace std;#define REP(i, N) for(int i = 0; i < (N); ++i)#define CLR(A,value) memset(A,value,sizeof(A))#define RI(n) scanf("%d", &n)#define RII(n, m) scanf("%d%d", &n, &m)#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)#define RS(s) scanf("%s", s)typedef long long LL;const int INF = 0x3f3f3f3f;const double eps = 1e-10;const int maxn = 111 * 310;int cost[111], money[111];int d[111][111];int dp[111][310];void floyed(int n){ REP(k, n) REP(i, n) REP(j, n) { if (d[i][k] == INF || d[k][j] == INF) continue; d[i][j] = min(d[i][j], d[i][k] + d[k][j]); }}int n, m, t, s, e;int id[111];int solve(){ int ans = 0; memset(dp, -1, sizeof(dp));///不能到达的为-1 for (int i = 0; i < n; i++) { int ct = d[s][i] + cost[i]; if (ct <= t) { dp[i][ct] = money[i]; if (ct + d[i][e] <= t) ans = max(ans, dp[i][ct]); } } for (int ii = 0; ii < n; ii++) { int i = id[ii]; for (int j = 0; j < n; j++) { if (i == j || money[i] >= money[j] || d[i][j] == INF) continue; for (int tt = 0; tt + d[i][j] + cost[j] <= t; tt++) { if (dp[i][tt] == -1) continue; int ct = tt + d[i][j] + cost[j]; if (dp[j][ct] < dp[i][tt] + money[j]) { dp[j][ct] = dp[i][tt] + money[j]; if (ct + d[j][e] <= t) ans = max(ans, dp[j][ct]); } } } } return ans;}bool cmp(int x, int y){ return money[x] < money[y];}int main (){ int test; RI(test); int ncase = 1; while (test--) { scanf("%d%d%d%d%d", &n, &m, &t, &s, &e); memset(d, INF, sizeof(d)); for (int i = 0; i < n; i++) d[i][i] = 0, id[i] = i; for (int i = 0; i < n; i++) RI(cost[i]); for (int i = 0; i < n; i++) RI(money[i]); for (int i = 0; i < m; i++) { int x, y, z; scanf("%d%d%d", &x, &y, &z); d[x][y] = min(d[x][y], z); d[y][x] = d[x][y]; } floyed(n); sort(id, id + n, cmp); int ans = solve(); printf("Case #%d:\n", ncase++); printf("%d\n", ans); } return 0;}
0 0
- HDU 4571 Travel in time (SPFA 或 dp)
- hdu 4571 Travel in time(SPFA+DP)
- Hdu 4571 Travel in time(dp)
- hdu 4571 Travel in time(floyd+dp)
- HDU 4571——Travel in time(dp)
- 2013 长沙邀请赛 HDU 4571 Travel in time(dp)
- HDU 4571 - Travel in time(Floyd+dijkstra+dp)
- HDU-4571 Travel in time (Floyd&&(DFS||DP))
- hdu 4571 Travel in time 最短路+dp
- hdu 4571 Travel in time
- hdu 4571 Travel in time
- HDU -4571--Travel in Time
- hdu 4571 Travel in time
- hdu 4571 Travel in time
- HDU-4571-Travel in time
- HDU 4571 Travel in time
- HDU 4571 Travel in time 解题报告
- floyd+动态规划 hdu-4571-Travel in time
- 图学PowerBuilder---智能提示功能
- ARM开发工具介绍
- Linux 命令大全
- Ubuntu下安装FTP服务(以VSFTPD为例
- 'telnet' is not recognized as an internal or external command
- HDU 4571 Travel in time (SPFA 或 dp)
- 什么是图像频率?
- css之不能移动的广告条
- 【算法入门经典】 第二章
- FILTER的执行次数和驱动表问题
- 【算法入门经典】 第三章
- C++中的默认函数与default和delete用法
- hive之UDF整理
- JAVA中静态的使用