标签:
题意比较容易明白:每个点有一个pow值,代表电力,要求从0号点派出一些坦克,占领这些点,使得占领的点的pow值总和大于整个图中的pow总之。且坦克耗费的总油最小,坦克数量不限。
思路,在求得单元最短路之后,以pow为背包,路径长度为物品,求解01背包。然后从pow总值的一半开始往后扫,得出油量(物品)最小值。
#include <iostream> #include <queue> #include <vector> #include <stdio.h> #define INF 100000000 using namespace std; int N,M; int dist[105]; int dp[10000000],pow[105]; struct node { int E,W; node(int ee,int ww):E(ee),W(ww){} node() {} friend bool operator<(node n1,node n2) { return n1.W>n2.W; } }; vector<vector<node> >v; void dijikstra() { for(int i=1;i<=N;i++) dist[i]=INF; dist[0]=0; priority_queue<node> Q; Q.push(node(0,0)); while(!Q.empty()) { node now=Q.top(); Q.pop(); int S=now.E; for(int i=0;i<v[S].size();i++) { if(dist[S]+v[S][i].W<dist[v[S][i].E]) { dist[v[S][i].E]=dist[S]+v[S][i].W; Q.push(node(v[S][i].E,dist[v[S][i].E])); } } } } int main() { int T,s,e,w,sum,ans; scanf("%d",&T); while(T--) { scanf("%d%d",&N,&M); v.clear(); v.resize(N+1); sum=0; while(M--) { scanf("%d%d%d",&s,&e,&w); v[s].push_back(node(e,w)); v[e].push_back(node(s,w)); } for(int i=1;i<=N;i++) { scanf("%d",&pow[i]); sum+=pow[i]; } dijikstra(); for(int i=1;i<=sum;i++) dp[i]=INF; dp[0]=0; for(int i=1;i<=N;i++) { for(int j=sum;j>=pow[i];j--) { dp[j]=min(dp[j],dp[j-pow[i]]+dist[i]); } } ans=INF; for(int i=sum/2+1;i<=sum;i++) ans=min(ans,dp[i]); if(ans==INF) cout<<"impossible"<<endl; else cout<<ans<<endl; } return 0; }
标签:
原文地址:http://www.cnblogs.com/modengdubai/p/4747612.html