题目
题意:每个坦克从0出发到1-n个城市 最终停在哪个城市会得到这个城市的电力。总部有多辆坦克。问得到总电力>= 所有城市的总电力的一半。走过的路最短为多少。
最短路+背包。。 。 。注意背包要装满 。
#include <queue>
#include <cmath>
#include <cstring>
#include <cstdio>
#define m(a,b) memset(a,b,sizeof a)
#define mak(a,b) make_pair(a,b)
#define sdd(a,b) scanf("%d%d",&a,&b)
#define pi pair<int,int>
using namespace std;
const int N=105+2;
const int M=10000+2;
const int INF=0x3f3f3f3f;
int tot,s,t,n,m;
int head[N],d[N],dp[M*100],w[N];
bool vis[N];
struct Edge{int to,len,nex;}edge[M*2];
priority_queue<pair<int,int> >q;
void add(int from,int to,int len)
{
edge[++tot]=(Edge){to,len,head[from]};head[from]=tot;
edge[++tot]=(Edge){from,len,head[to]};head[to]=tot;
}
void dijkstra()
{
while(!q.empty())
q.pop();
d[0]=0;
q.push(mak(0,0));
vis[0]=0;
while(!q.empty())
{
int x=q.top().second;
q.pop();
if(vis[x])
continue;
vis[x]=1;
for(int i=head[x];i;i=edge[i].nex)
{
int y=edge[i].to,l=edge[i].len;
if(d[y]>d[x]+l)
{
d[y]=d[x]+l;
q.push(mak(-d[y],y));
}
}
}
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
sdd(n,m);
m(head,0);
m(d,INF);
tot=0;
for(int i=0;i<=n;i++)
head[i]=0,d[i]=INF,vis[i]=0;
int a,b,l;
while(m--)
{
scanf("%d%d%d",&a,&b,&l);
add(a,b,l);
}
dijkstra();
int sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&w[i]);
sum+=w[i];
}
int x=sum/2+1;
// int D=0;
// for(int i=1;i<=n;i++)
// if(d[i]!=INF)
// D+=d[i];
// for(int i=1;i<=D;i++)
// dp[i]=-INF;
// for(int i=1;i<=n;i++)
// {
// if(d[i]==INF)
// continue;
// for(int j=D;j>=d[i];j--)
// dp[j]=max(dp[j],dp[j-d[i]]+w[i]);
// }
// bool flag=0;
// for(int i=0;i<=D;i++)
// if(dp[i]>=x)
// {
// printf("%d\n",i);
// flag=1;
// break;
// }
// if(!flag)
// puts("impossible");
//路径长度作为背包容量 sum作为价值
//----------------------------------------------------------------
//sum作为容量,d[i]作为价值 最短路径即为最小价值
for(int i=1;i<=sum;i++)
dp[i]=INF;
dp[0]=0;
for(int i=1;i<=n;i++)
{
if(d[i]==INF)
continue;
for(int j=sum;j>=w[i];j--)
{
dp[j]=min(dp[j],dp[j-w[i]]+d[i]);
}
}
int ans=INF;
for(int i=x;i<=sum;i++)
ans=ans<dp[i]?ans:dp[i];
if(ans!=INF)
printf("%d\n",ans);
else
puts("impossible");
}
}