http://acm.hdu.edu.cn/showproblem.php?pid=4284
题意:
题目:给出一些城市,从1出发,旅游一圈回到1,由于花费可能不够,所以选择一些城市打工,打工之前需要花费d买一个证,工资为c。选中的城市必须去工作一次,而且只能工作一次,问能不能完成旅行
这道 题 比赛是想的是 先 floyd 在 暴搜 ,结果 tle 赛后 看到 有人 暴搜 过了 ,,,,好无语(自己 考虑的 情况太多了)。。。。。。
题解:
首先 因为 我们 要用到的 只有 H 个点,所以我们先用 floyd 处理一下 ,构建一个 新图 ,在新图上处理,枚举 所有状态
首先 暴搜 的 时间复杂度为 O(15 !),要超啊,状态压缩 O(H * H * 2^H);可以接受 ;
dp[sta][i] 表示 状态 sta 最后一个工作的 节点 为 i 所剩的 最多钱数
1 #include<cstdio>
2 #include<cstring>
3 #include<cmath>
4 #include<iostream>
5 #include<algorithm>
6 #include< set>
7 #include<map>
8 #include<queue>
9 #include<vector>
10 #include< string>
11 #define Min(a,b) a<b?a:b
12 #define Max(a,b) a>b?a:b
13 #define CL(a,num) memset(a,num,sizeof(a));
14 #define eps 1e-12
15 #define inf 100000
16
17 // freopen("data.txt","r",stdin);
18 const double pi = acos(- 1.0);
19 typedef __int64 ll;
20 using namespace std;
21 int H,n,m,mon,sta,st;
22 int dp[ 1 << 17][ 20] ,mat[maxn][maxn],a[ 20];
23 struct node
24 {
25 int ci;
26 int di ;
27 }p[maxn] ;
28 void floyd()
29 {
30 for( int k = 1;k<=n;k++)
31 {
32 for( int i = 1; i <= n;i++ )
33 {
34 for( int j = 1; j<= n;j++)
35 {
36 if(mat[i][j] > mat[i][k] + mat[k][j])
37 {
38 mat[i][j] = mat[i][k] + mat[k][j] ;
39 }
40 }
41 }
42 }
43
44 }
45 void solve()
46 {
47 sta = 1 << H ;
48 int i,j,k;
49 CL(dp,- 1);
50
51 for(i = 1;i<=H;i++) // 注意这 每一次 要 从 1 开始 出发,H 中 有没有 1 无所谓
52 {
53 int tp = mon - mat[ 1][a[i]] - p[i].di ;
54 if(tp >= 0)
55 dp[ 1<<(i - 1)][i] = tp + p[i].ci ;
56 }
57
58 for(i = 0 ;i < sta;i++)
59 {
60 for(j = 1;j<=H;j++)
61 {
62 if(dp[i][j] < 0) continue ;
63
64 int u = a[j] ;
65
66 if(i & 1 <<(j - 1) == 0) continue ;
67
68
69 for(k = 1;k<=H;k++)
70 {
71 int v = a[k];
72 if(i & 1 << (k - 1)) continue ;
73
74 int t = i | 1 <<(k - 1) ;
75
76 if(dp[i][j] >= mat[u][v] + p[k].di)
77 {
78 if(dp[t][k] < dp[i][j] - mat[u][v] - p[k].di + p[k].ci);
79 dp[t][k] = dp[i][j] - mat[u][v] - p[k].di + p[k].ci;
80 }
81
82
83 }
84 }
85 }
86 }
87 void init()
88 {
89 for( int i = 0 ; i <= n;i++)
90 {
91 for( int j = 0 ;j<= n;j++)
92 {
93 mat[i][j] =inf ;
94 if(i == j)
95 {
96 mat[i][j] = 0;
97 }
98 }
99 }
100 }
101 int main()
102 {
103 // freopen("data.txt","r",stdin);
104 int t,i,j,x,y,len;
105 scanf( " %d ",&t);
106 while(t--)
107 {
108 scanf( " %d%d%d ",&n,&m,&mon);
109 init() ;
110 for(i = 0 ;i< m;i++)
111 {
112 scanf( " %d%d%d ",&x,&y,&len);
113 if(mat[x][y] > len)
114 mat[x][y] = mat[y][x] = len ;
115 }
116 floyd() ;//在原图上 构建的新图
117
118 scanf( " %d ",&H);
119 int f = 0;
120 for(i = 1 ;i<= H;i ++ )
121 {
122 scanf( " %d %d %d ",&a[i],&p[i].ci,&p[i].di);
123
124 }
125
126
127
128 solve();
129 int flag = 0;
130
131 for(i = 1 ; i<= H;i++)
132 {
133 if(dp[sta - 1][i] >= mat[a[i]][ 1])
134 {
135
136 flag = 1;
137 break ;
138 }
139 }
140 if(flag)puts( " YES ");
141 else puts( " NO ");
142 }
143 }
2 #include<cstring>
3 #include<cmath>
4 #include<iostream>
5 #include<algorithm>
6 #include< set>
7 #include<map>
8 #include<queue>
9 #include<vector>
10 #include< string>
11 #define Min(a,b) a<b?a:b
12 #define Max(a,b) a>b?a:b
13 #define CL(a,num) memset(a,num,sizeof(a));
14 #define eps 1e-12
15 #define inf 100000
16
17 // freopen("data.txt","r",stdin);
18 const double pi = acos(- 1.0);
19 typedef __int64 ll;
20 using namespace std;
21 int H,n,m,mon,sta,st;
22 int dp[ 1 << 17][ 20] ,mat[maxn][maxn],a[ 20];
23 struct node
24 {
25 int ci;
26 int di ;
27 }p[maxn] ;
28 void floyd()
29 {
30 for( int k = 1;k<=n;k++)
31 {
32 for( int i = 1; i <= n;i++ )
33 {
34 for( int j = 1; j<= n;j++)
35 {
36 if(mat[i][j] > mat[i][k] + mat[k][j])
37 {
38 mat[i][j] = mat[i][k] + mat[k][j] ;
39 }
40 }
41 }
42 }
43
44 }
45 void solve()
46 {
47 sta = 1 << H ;
48 int i,j,k;
49 CL(dp,- 1);
50
51 for(i = 1;i<=H;i++) // 注意这 每一次 要 从 1 开始 出发,H 中 有没有 1 无所谓
52 {
53 int tp = mon - mat[ 1][a[i]] - p[i].di ;
54 if(tp >= 0)
55 dp[ 1<<(i - 1)][i] = tp + p[i].ci ;
56 }
57
58 for(i = 0 ;i < sta;i++)
59 {
60 for(j = 1;j<=H;j++)
61 {
62 if(dp[i][j] < 0) continue ;
63
64 int u = a[j] ;
65
66 if(i & 1 <<(j - 1) == 0) continue ;
67
68
69 for(k = 1;k<=H;k++)
70 {
71 int v = a[k];
72 if(i & 1 << (k - 1)) continue ;
73
74 int t = i | 1 <<(k - 1) ;
75
76 if(dp[i][j] >= mat[u][v] + p[k].di)
77 {
78 if(dp[t][k] < dp[i][j] - mat[u][v] - p[k].di + p[k].ci);
79 dp[t][k] = dp[i][j] - mat[u][v] - p[k].di + p[k].ci;
80 }
81
82
83 }
84 }
85 }
86 }
87 void init()
88 {
89 for( int i = 0 ; i <= n;i++)
90 {
91 for( int j = 0 ;j<= n;j++)
92 {
93 mat[i][j] =inf ;
94 if(i == j)
95 {
96 mat[i][j] = 0;
97 }
98 }
99 }
100 }
101 int main()
102 {
103 // freopen("data.txt","r",stdin);
104 int t,i,j,x,y,len;
105 scanf( " %d ",&t);
106 while(t--)
107 {
108 scanf( " %d%d%d ",&n,&m,&mon);
109 init() ;
110 for(i = 0 ;i< m;i++)
111 {
112 scanf( " %d%d%d ",&x,&y,&len);
113 if(mat[x][y] > len)
114 mat[x][y] = mat[y][x] = len ;
115 }
116 floyd() ;//在原图上 构建的新图
117
118 scanf( " %d ",&H);
119 int f = 0;
120 for(i = 1 ;i<= H;i ++ )
121 {
122 scanf( " %d %d %d ",&a[i],&p[i].ci,&p[i].di);
123
124 }
125
126
127
128 solve();
129 int flag = 0;
130
131 for(i = 1 ; i<= H;i++)
132 {
133 if(dp[sta - 1][i] >= mat[a[i]][ 1])
134 {
135
136 flag = 1;
137 break ;
138 }
139 }
140 if(flag)puts( " YES ");
141 else puts( " NO ");
142 }
143 }