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 }