http://acm.hdu.edu.cn/showproblem.php?pid=3339
题意:
是n个发电站,m条路,每条路有各自的距离,每个发电站有各自的发电量,现在需要炸毁它们,一辆坦克只能炸毁一个发电站,而且需要炸毁的发电厂的发电量需要大于所有发电站所产生的总电量的一半,求坦克走的最短距离。
因为题目说明不超过100个点,所以可以用弗洛伊德算法,把所有的0到各个发电站的距离找出来,然后把0能到的各个发电站的距离相加作为背包的容量,以dp数组储存的值作为炸毁的发电站的电量,最后进行判断,如果dp[i]的值大于所有发电站的总电量,输出i的值,此时i的值就是坦克炸毁发电站使城市供电瘫痪所能走的最短距离
2.
题目意思:有一基地0,和n个发电站,每个发电站有能量P[i],现在基地想要使所有的发电站不能正常工作,那么得用坦克占领所有发电站的能量总和的一半多,那么要占领哪几个发电站就能拥有总能量的一半多,从而控制所有的发电站,占领K个发电站需K辆坦克.每辆坦克从基地出发,如果能实现就输出每辆坦克所花费的总和.
分析:
一:解决每个站到其地的最小距离. 二:从n个发电站中找出几个站的能量和超出总能量和的一半并且这几个站到基地的距离和最小.
第一个问题很好解决,要解决每二个问题,就可以用01背包了,把n个站到基地的总距离和看成背包的最大容量V,能量看成是价值,也就是求花最少的费用能得到的最大价值.注意了,每个包是恰好被装满.
错误
#include<string.h> #include<stdlib.h> #include<stdio.h> #include<iostream> #define inf 0x3f3f3f3f const int maxn=110; int t,m,n; int mmp[maxn][maxn]; int vis[maxn],dis[maxn]; int a[maxn],dp[maxn]; void floyd() { int i,j,k; for(k=0; k<=n; k++) for(i=0; i<=n; i++) for(j=0; j<=n; j++) { if(mmp[i][k]+mmp[k][j]<mmp[i][j]) mmp[i][j]=mmp[i][k]+mmp[k][j]; } } using namespace std; int main() { ios::sync_with_stdio(false); int u,v,w; cin>>t; while(t--) { cin>>n>>m; int ans,sum; ans=sum=0; for(int i=0; i<=n; i++) for(int j=0; j<=n; j++) { mmp[i][j]=(i==j?0:inf); } for(int i=0; i<m; i++) { cin>>u>>v>>w; if(mmp[u][v]>w) mmp[u][v]=mmp[v][u]=w; } floyd(); for(int i=1; i<=n; i++) { cin>>a[i]; sum+=a[i]; if(mmp[0][i]!=inf) ans+=mmp[0][i]; } memset(dp,0,sizeof(dp)); for(int i=1; i<=n; i++) for(int j=ans; j>=mmp[0][i]; j--) { if(dp[j]<dp[j-mmp[0][i]]+a[i]) dp[j]=dp[j-mmp[0][i]]+a[i]; } int flag=0; for(int i=1; i<=ans; i++) { if(dp[i]>sum/2.0) { flag=1; cout<<i<<endl; break; } } if(flag==0) cout<<"impossible"<<endl; } return 0; }