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 }

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4284

原文地址:https://www.cnblogs.com/Griselda/p/2687188.html