題目:
連結點選打開連結
題意:
有N個發電站和M條路,給出每兩條路之間的耗油量,then,N行代表發電站的能量。求最小耗油量,隻有控制超過總能量的一半,才能成功,否則impossible。
思路:
求最少的耗油量,明顯是最短路問題,然後,要求控制的電量要超過一半用01背包解決:V是總電量一半+1,dijkstra求得的dis[]是價值,每個發電站的電量v[]是花費。
代碼:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 100000000
using namespace std;
int n,m;
int map[110][110],dis[110];
int dp[10010],v[110];
int result;
void dijkstra()
{
int vis[110];
memset(vis,0,sizeof(vis));
for(int i=1; i<=n; i++)
{
dis[i] = map[0][i];
}
dis[0] = 0;
for(int i=1; i<n; i++)
{
int x,minn = INF;
for(int y=1; y<=n; y++)
{
if(!vis[y] && minn > dis[y])
minn = dis[x=y];
}
vis[x] = 1;
for(int y=1; y<=n; y++)
{
if(dis[y] > dis[x] + map[x][y])
dis[y] = dis[x] + map[x][y];
}
}
}
int main()
{
//freopen("input.txt","r",stdin);
int t;
int st,ed,di;
cin>>t;
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=0; i<=n; i++)
{
for(int j=0; j<=n; j++)
map[i][j] = INF;
}
for(int i=0; i<m; i++)
{
scanf("%d%d%d",&st,&ed,&di);
if(map[st][ed] > di)
map[st][ed] = map[ed][st] = di;
}
int sum = 0;
for(int i=1; i<=n; i++)
{
scanf("%d",&v[i]);
sum += v[i];
}
dijkstra();//最短路求從0到每個發電站的耗油量,即dis[],01背包中的價值
for(int i=1; i<=sum; i++)
{
dp[i] = INF;
}
dp[0] = 0;
for(int i=1; i<=n; i++)//01背包求最小
{
for(int j=sum; j>=v[i]; j--)
dp[j] = min(dp[j],dp[j-v[i]] + dis[i]);
}
int V = sum/2 + 1;//背包容量為大于總電量和的一半
int result = INF;
for(int i=V; i<=sum; i++)
{
if(dp[i] < result)
result = dp[i];
}
if(result == INF)
printf("impossible\n");
else
printf("%d\n",result);
}
return 0;
}
-------------------------------------------------------------------------------------------
戰鬥,從不停歇;奮鬥,永不停歇~~~~~~~~~~~~~~~~~~~~~~~