hdu 4284 Travel (floyd + 状态 dp 2012 ACM/ICPC Asia Regional Tianjin Online )

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 }
原文地址:https://www.cnblogs.com/acSzz/p/2682207.html