Hdu 4284 状态DP 能否走完所选城市.cpp
题意:
已知s.b原来有多少钱 in
以及知道 m 个去他想去的城市工作需要用多少钱以及能挣到多少钱
然后知道他从 a 城市到 b 城市得花多少钱..
问他能不能去完他想去的城市??
给出一个 T 表示样例个数
接下来每个样例给出一个 n m in
表示有 n 个点 m 个想去的地方
接下来 m 行..每行给出 a b w 代表 a 城市和 b 城市之间路费为 w
然后有一个 h 表示他想去的城市个数
接下来 h 行..给出 a c d 代表在a城市需要花d元 能够挣 c 元
思路:
状态压缩DP..
求出城市间最短距离
初始状态是如果从第一个城市到第 i 个城市的路费+花费 >= 0 就让这个dp[ 1<< i ][ i ]的值更新为 剩下的钱+挣的钱
然后枚举所有的状态
枚举所有的可能性..找出按某个顺序能挣得的钱越多的..
然后如果最后所有方案中有一个的钱的总数 >= 0就代表他可以走遍他想去的城市..
Tips:
因为可能出现重边 所以要加判断语句
dis的初始化对dis[ i ][ i ] = 0;
Code:
View Code
1 #include <stdio.h> 2 #include <cstring> 3 using namespace std; 4 #define clr(x) memset(x, 0, sizeof(x)) 5 const int INF = 0x1f1f1f1f; 6 #define max(a, b) ((a) > (b)?(a):(b)) 7 8 int T, n, m, h, a, b, c, d, w, in; 9 int dis[110][110], dp[1<<15][15]; 10 bool flag; 11 12 struct CD 13 { 14 int num; 15 int c; 16 int d; 17 }cd[15]; 18 19 void floyd() 20 { 21 for(int k = 1; k <= n; ++k) 22 for(int i = 1; i <= n; ++i) 23 for(int j = 1; j <= n; ++j) { 24 dis[i][j] = dis[i][j]<dis[i][k]+dis[k][j]?dis[i][j]:dis[i][k]+dis[k][j]; 25 } 26 } 27 28 void solve() 29 { 30 int i, j, k; 31 int tmp, st, stat; 32 33 st = (1<<h)-1; 34 memset(dp, 0xff, sizeof(dp)); 35 36 floyd(); 37 for(i = 0; i < h; ++i) { 38 tmp = in-dis[1][cd[i].num]-cd[i].d; 39 if(tmp >= 0) { 40 dp[1<<i][i] = tmp+cd[i].c; 41 } 42 } 43 44 for(i = 1; i <= st; ++i) 45 for(j = 0; j < h; ++j) 46 if(dp[i][j] >= 0) { 47 for(k = 0; k < h; ++k) 48 if(!(i&(1<<k))) { 49 tmp = dp[i][j] - dis[cd[j].num][cd[k].num] - cd[k].d; 50 if(tmp >= 0) { 51 stat = i+(1<<k); 52 dp[stat][k] = max(dp[stat][k], tmp+cd[k].c); 53 } 54 } 55 } 56 57 for(i = 0; i < h; ++i) { 58 tmp = dp[st][i]-dis[cd[i].num][1]; 59 if(tmp >= 0) { 60 flag = true; 61 break; 62 } 63 } 64 } 65 66 int main() 67 { 68 int i, j, k; 69 while(scanf("%d", &T) != EOF) 70 while(T--) 71 { 72 memset(dis, INF, sizeof(dis)); 73 flag = false; 74 for(i = 1; i <= n; ++i) 75 dis[i][i] = 0; 76 77 scanf("%d %d %d", &n, &m, &in); 78 while(m--) { 79 scanf("%d %d %d", &a, &b, &w); 80 if(w < dis[a][b]) 81 dis[a][b] = dis[b][a] = w; 82 } 83 scanf("%d", &h); 84 for(i = 0; i < h; ++i) 85 scanf("%d %d %d", &cd[i].num, &cd[i].c, &cd[i].d); 86 87 solve(); 88 89 if(flag) puts("YES"); 90 else puts("NO"); 91 } 92 return 0; 93 }