hdu 3339(01背包+最短路)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3339

大致题意是说:有n个电站,每个电站都有一定的电量,电站之间有一定距离,我们要从0点出发去占领一些电站,使得占领的电站电量之和超过总电量的一半,求达到条件所要走的最短距离。如果可能的话,输出距离,否则输出不可能。

思路:我们从0点开始派出一些tank去占领一些电站,坦克到每个电站都有一定距离,而占领每个电站之后可以得到一定电量,距离就相当于体积v,电量就相当于价值w,这不是就01背包吗?01背包通常的问法是给定体积,求获得最大的价值,这里的问法是给定价值,求恰好得到或多于该价值时的最小体积。我们只要从前向后搜索,找到第一个大于该价值的体积即可。

不过一开始我就被坑了,我令inf=0x7fffffff,然后就wa了好多次,最后该成小一些的数,就过了,orz;

View Code
 1 #include<iostream>

 2 #include<cstring>

 3 const int N=111;

 4 const int inf=0x7fffff;

 5 using namespace std;

 6 int n,m;

 7 int edge[N][N];

 8 int visited[N];

 9 int dist[N];

10 int dp[N*N],power[N];

11 

12 void Dijkstra(int v0){

13     memset(visited,0,sizeof(visited));

14     for(int i=1;i<=n;i++){

15         dist[i]=edge[v0][i];

16     }

17     visited[v0]=1;

18     for(int i=1;i<n;i++){

19         int min=inf,u=v0;

20         for(int j=1;j<=n;j++){

21             if(!visited[j]&&dist[j]<min){

22                 min=dist[j],u=j;

23             }

24         }

25         if(min==inf)return ;

26         visited[u]=1;

27         for(int k=1;k<=n;k++){

28             if(!visited[k]&&dist[u]+edge[u][k]<dist[k]){

29                 dist[k]=dist[u]+edge[u][k];

30             }

31         }

32     }

33 }

34 

35 int main(){

36     int _case;

37     scanf("%d",&_case);

38     while(_case--){

39         scanf("%d%d",&n,&m);

40         for(int i=0;i<=n;i++){

41             for(int j=0;j<=n;j++){

42                 if(i==j){

43                     edge[i][j]=0;

44                 }else 

45                     edge[i][j]=inf;

46             }

47         }

48         int x,y,d;

49         for(int i=1;i<=m;i++){

50             scanf("%d%d%d",&x,&y,&d);

51             if(d<edge[x][y]){

52                 edge[x][y]=edge[y][x]=d;

53             }

54         }

55         for(int i=1;i<=n;i++){

56             scanf("%d",&power[i]);

57         }

58         Dijkstra(0);

59         bool flag=true;

60         int v=0,w=0;

61         for(int i=1;i<=n;i++){

62             w+=power[i];

63             v+=dist[i];

64             if(dist[i]==inf){

65                 flag=false;

66                 break;

67             }

68         }

69         if(!flag){

70             printf("impossible\n");

71             continue;

72         }

73         for(int i=0;i<=v;i++){

74             dp[i]=0;

75         }

76         for(int i=1;i<=n;i++){

77             for(int j=v;j-dist[i]>=0;j--){

78                 dp[j]=(dp[j-dist[i]]+power[i])>dp[j]?(dp[j-dist[i]]+power[i]):dp[j];

79             }

80         }

81         w=w/2+1;

82         for(int i=1;i<=v;i++){

83             if(dp[i]>=w){

84                 printf("%d\n",i);

85                 break;

86             }

87         }

88     }

89     return 0;

90 }

 

你可能感兴趣的:(HDU)