您的位置:首页 > 其它

hdu 3339 最短路+背包

2014-03-21 00:03 225 查看
/*
题意:给出一个0~n组成的图,1~n的点上分布着值为pow的电站,给出图的m条边以及
距离,从0出发到n个点中的x个点的行走距离和最小,且x个点的pow之和必须超过总的pow
和的一半;

题解:最短路+01背包
先求出0到所有点的最短距离,然后通过以行走的距离为背包,pow的和为价值,设将所有
点遍历走的距离值为sum,即要求0~sum的dp值,即当距离为v时,dp[v]为pow的最大的和,
因此dp完之后从0~sum遍历找出最小的v满足pow的和大于总和一半即可。

注意:重边、不连通的点、是多于一半的power,等于不行
*/
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>

#define Max 1000000001

using namespace std;

struct nod
{
int power;
int oil;
}s[105];

int p;
int dp[60050],dist[105];
int map[105][105];
bool vis[105];

void dijkstra(int next, int n)//迪杰斯特拉算法求最短路,next为起点
{
for(int i=0; i<=n; i++)
dist[i] = Max;
memset(vis,false,sizeof(vis));
dist[next] = 0;
for(int i=0; i<=n; i++)
{
int mindis = Max;
for(int j=0; j<=n; j++)
{
if (!vis[j] && dist[j] < mindis)//找出未访问的点中路径最短的点并赋给node
{
mindis = dist[j];
next = j;
}
}
if (mindis == Max)//当点已经遍历完,break;
break;
vis[next] = true;
for(int j=0; j<=n; j++)
if (!vis[j] && map[next][j] > 0 && dist[next]+map[next][j] < dist[j])
//以next为基点对其它未访问的点进行松弛
dist[j] = dist[next]+map[next][j];
}
}

bool cmp(nod a, nod b)
{
return a.oil < b.oil;
}

int main(void)
{
int n,q,fr,to,price,allpower;
cin >> n;
while (n--)
{
cin >> p >> q;
allpower = 0;
for(int i=0; i<=p; i++)
for(int j=0; j<=p; j++)
{
map[i][j] = Max;
}
while (q--)
{
cin >> fr >> to >> price;
if (map[fr][to] > price)
map[fr][to] = map[to][fr] = price;
}
for(int i=1; i<=p; i++)
{
cin >> s[i].power;
allpower += s[i].power;
}
dijkstra(0,p);
int alloil, num;
alloil = 0;
num = 0;
for(int i=1; i<=p; i++)
{
if (dist[i] < Max)
{
alloil += dist[i];
num++;
}
s[i].oil = dist[i];
}
sort(s+1,s+p+1,cmp);
int ans = 0;
memset(dp,0,sizeof(dp));
for(int i=1; i<=num; i++)
for(int v = alloil; v >= s[i].oil; v--)
dp[v] = max(dp[v],dp[v-s[i].oil] + s[i].power);
int i;
for(i=0; i<=alloil; i++)
if (dp[i] >= allpower/2+1)
break;
if (i <= alloil)
cout << i << endl;
else
cout << "impossible" << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: