HDU3339 Floyd+01背包

题意:给定一张图,每个点都有一个power值,到每个点都要一定的距离 消耗一定的油量,求从0出发到某些点 使得 油量消耗最少且power值达到一半。

可以floyd或者spfa求出0到各点的距离 dis[ maxm ]。

然后就可以转化为:从dis[]中挑出某些点,使得距离和最小且power值达到某个值。

从01背包中可以发现:从给定的一些物品中挑出一些放入一个背包中,使得不超过背包体积。

这是我们可以把dis当做每个物品的体积,power当做价值。

然后从dp中搜到一个power值满足条件的最小的 i 即可

View Code
 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn = 105;
 6 const int maxm = 1000005;
 7 const int inf = 99999999;
 8 int mat[ maxn ][ maxn ],power[ maxn ],dis[ maxn ];
 9 int dp[ maxm ];
10 int sum,aim;
11 //power 相当于价值,dis 相当于体积
12 void init( int n ){
13     for( int i=0;i<=n;i++ )
14         for( int j=0;j<=n;j++ )
15             mat[ i ][ j ]=inf;
16 }
17 void floyd( int n ){
18     for( int k=0;k<=n;k++ ){
19         for( int i=0;i<=n;i++ ){
20             for( int j=0;j<=n;j++ ){
21                 if( mat[i][k]!=inf&&mat[k][j]!=inf&&mat[i][j]>mat[i][k]+mat[k][j] ){
22                     mat[i][j]=mat[i][k]+mat[k][j];
23                 }
24             }
25         }
26     }
27     for( int i=1;i<=n;i++ ){
28         dis[i]=mat[0][i];
29         if( dis[i]!=inf )
30             sum+=dis[i];
31     }
32 }
33 int main(){
34     int T;
35     scanf("%d",&T);
36     while( T-- ){
37         int n,m;
38         scanf("%d%d",&n,&m);
39         init( n );
40         int a,b,c;
41         while( m-- ){
42             scanf("%d%d%d",&a,&b,&c);
43             mat[ a ][ b ]=mat[ b ][ a ]=min(mat[a][b],c);
44         }
45         sum=aim=0;
46         for( int i=1;i<=n;i++ ){
47             scanf("%d",&power[ i ]);
48             aim+=power[ i ];
49         }
50         floyd( n );
51         //dp
52         //sum/=2;
53         memset( dp,0,sizeof( dp ));
54         for( int i=1;i<=n;i++ ){
55             for( int j=sum;j>=dis[i];j-- ){
56                 dp[ j ]= max( dp[ j ],dp[ j-dis[i] ]+power[ i ] );
57             }
58         }
59         int ans=inf;
60         for( int i=0;i<=sum;i++ )
61             if( dp[i]>=(aim/2+1)&&dp[i]<ans ){
62                 ans=i;
63                 break;
64             }
65         if( ans==inf )
66             printf("impossible\n");
67         else
68             printf("%d\n",ans);
69     }
70     return 0;
71 }
keep moving...
原文地址:https://www.cnblogs.com/xxx0624/p/2932873.html