题意大意就是说:有n个电站,每个电站都有一定的电量,电站之间有一定的距离,我们要从0点出发去占据一些电站,使得占据的电站电量之和不小于总电量的一半,求达到要求所要走的最短距离。若是可能的话,输出间隔,不然输出不成能。我们知道电站都是连通的,只要0点与任何一个电站连通,我们就可以占据所有电站,若是0点不与任何一个电站相连,就是不成能实现,也就是说0点到任何一个电站的间隔都是无穷。
我们从0点开端派出一些坦克去占据一些电站,坦克到每个电站都有必然间隔,而占据每个电站之后可以获得必然电量,间隔就相当于体积,电量就相当于价值,这不是就01背包吗?01背包凡是的问法是给定体积,求获得最大的价值,这里的问法是给订价值,求正好获得或多于该价值时的最小体积。我们只要畴前向后搜刮,找到第一个大于该价值的体积即可。
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <math.h>
#define INF 999999999
#define M 105
using namespace std;
int main()
{
int map[M][M],p[M],dp[M*M];
int n,m,t,i,j,k,sum,ave;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(i=0;i<=n;i++)
{
for(j=0;j<=n;j++)
{
map[i][j]=INF;
}
}
while(m--)
{
int u,v,d;
scanf("%d%d%d",&u,&v,&d);
map[u][v]=map[v][u]=min(map[u][v],d);
}
sum=0;
for(i=1;i<=n;i++)
{
scanf("%d",&p[i]);
sum+=p[i];
}
ave=sum/2;
for(k=0;k<=n;k++)
{
for(i=0;i<=n;i++)
{
for(j=0;j<=n;j++)
{
map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
}
}
}
int temp=0;
for(i=1;i<=n;i++)
{
if(map[0][i]<INF-10)
temp+=map[0][i];
}
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{
for(j=temp;j>=map[0][i];j--)
{
dp[j]=max(dp[j],dp[j-map[0][i]]+p[i]);
}
}
int flag=0;
for(i=0;i<=temp;i++)
{
if(dp[i]>ave)
{
printf("%d\n",i);
flag=1;
break;
}
}
if(flag==0)
printf("impossible\n");
}
return 0;
}