• 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 }
  • 相关阅读:
    Android 程序员必须知道的 53 个知识点
    2017.8.27 考试
    hdu 3118 Arbiter
    UVA 1575 Factors
    [HNOI2008]Cards
    JSOI2008 小店购物
    hdu 2121 Ice_cream’s world II
    poj 3164 Command Network(最小树形图模板)
    [USACO14MAR] Counting Friends
    UVA 10479 The Hendrie Sequence
  • 原文地址:https://www.cnblogs.com/wally/p/2948158.html
Copyright © 2020-2023  润新知