hdu3339 In Action(Dijkstra+01背包)

简介:

/*
   题意:有 n 个站点(编号1...n),每一个站点都有一个能量值,为了不让这些能量值连接起来,要用 
   坦克占领这个站点!已知站点的 之间的距离,每个坦克从0点出发到某一个站点,1 unit distance costs 1 unit oil!
   最后占领的所有的站点的能量值之和为总能量值的一半还要多,问最少耗油多少!
    
*/

/*
     思路:不同的坦克会占领不同的站点,耗油最少那就是路程最少,所以我们先将从 0点到其他各点的
     最短距离求出来!也就是d[i]的值!然后我们又知道每一个站点的所具有的能量值!也就是w[i];
     最后求出满足占领站点的能量比总能量的一半多并且路程最少。。。直接01背包走起! 
*/ 
#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#define N 10005
#define INF 0x3f3f3f3f
using namespace std;

int w[105];

struct EDGE{
   int u, v, nt, dist;
   EDGE(){}
   
   EDGE(int u, int v, int nt, int dist){
      this->u=u;
      this->v=v;
      this->nt=nt;
      this->dist=dist;
   }
};

EDGE edge[N*2];
int first[105];
int cnt;
queue<pair<int, int> >q;
int n, m;
int dp[10005];
int d[105];
int map[105][105];

void addEdge(int u, int v, int dist){
    edge[cnt++]=EDGE(u, v, first[u], dist);
    first[u]=cnt-1;
    edge[cnt++]=EDGE(v, u, first[v], dist);
    first[v]=cnt-1;
}

void Dijkstra(){
   d[0]=0;
   q.push(make_pair(0, 0)); 
   while(!q.empty()){
       pair<int,int> cur=q.front();
       q.pop();
       int u=cur.second;
       if(d[u] != cur.first) continue;
       for(int e=first[u]; e!=-1; e=edge[e].nt){
              int v=edge[e].v, dist=edge[e].dist;
              if(d[v] > d[u] + dist){
                 d[v] = d[u] + dist;
                 q.push(make_pair(d[v], v));
              }
       }
   }
}

int main(){
   int t;
   int sumP, sumD;
   scanf("%d", &t);
   while(t--){
      scanf("%d%d", &n, &m);
      cnt=0;
      memset(d, 0x3f, sizeof(d));
      memset(first, -1, sizeof(first));
      for(int i=0; i<=n; ++i)
         for(int j=0; j<=n; ++j)
            map[i][j]=INF;
      while(m--){
          int u, v, dist;
          scanf("%d%d%d", &u, &v, &dist);
          if(map[u][v]>dist)
              map[u][v]=map[v][u]=dist;
      }
      for(int i=0; i<=n; ++i)
         for(int j=0; j<=i; ++j)
            if(map[i][j]!=INF)
              addEdge(i, j, map[i][j]); 
      Dijkstra();//求出 0点到其他个点的最短的距离! 
      sumP=sumD=0;
      for(int i=1; i<=n; ++i){
         scanf("%d", &w[i]);
         sumP+=w[i];
         sumD+=d[i];
      }
      memset(dp, 0x3f, sizeof(dp));//初始背包的总价值为无穷大 
      dp[0]=0;
      
      //zeroOnePackage... d[i]相当于价值(也就是耗油量), w[i]相当于容积(也就是能量值) 
      for(int i=1; i<=n; ++i) 
         for(int j=sumP; j>=w[i]; --j)
            dp[j]=min(dp[j], dp[j-w[i]]+d[i]);
      
      int maxCost=INF;
      for(int i=sumP/2+1; i<=sumP; ++i)//注意是sumP/2+1(因为要比一半多) 
            if(maxCost>dp[i])
               maxCost=dp[i];
      if(maxCost==INF)
         printf("impossible\n");
      else printf("%d\n", maxCost);
   }
   return 0;
}

/*
   思路:dp[i][j]表示到达 i站点, 并且占领的能量值为 j时的耗油最小值! 
         开始想用的是spfa算法,并且在进行节点之间距离松弛的时候,也将       背包融进来,但是超时啊!
         好桑心..... 
*/

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#define N 10005
#define INF 0x3f3f3f3f
using namespace std;

int w[105];

struct EDGE{
   int u, v, nt, dist;
   EDGE(){}
   
   EDGE(int u, int v, int nt, int dist){
      this->u=u;
      this->v=v;
      this->nt=nt;
      this->dist=dist;
   }
};

EDGE edge[N*2];
int first[105];
int cnt;
queue<pair<int, int> >q;
int vis[105];
int n, m, sum;
int dp[105][10005];
int map[105][105];

void addEdge(int u, int v, int dist){
    edge[cnt++]=EDGE(u, v, first[u], dist);
    first[u]=cnt-1;
    edge[cnt++]=EDGE(v, u, first[v], dist);
    first[v]=cnt-1;
}

void spfa(){
   dp[0][0]=0;
   q.push(make_pair(0, 0)); 
   vis[0]=1;
   while(!q.empty()){
       pair<int,int> cur=q.front();
       q.pop();
       int u=cur.second;
       vis[u]=0;
       for(int e=first[u]; e!=-1; e=edge[e].nt){
           int v=edge[e].v, dist=edge[e].dist;
           for(int j=w[v]; j<=sum; ++j)
              if(dp[v][j] > dp[u][j-w[v]] + dist){
                 dp[v][j] = dp[u][j-w[v]] + dist;
                 if(!vis[v]){
                    vis[v]=1;
                    q.push(make_pair(dp[v][j], v));
                 }
              }
       }
   }
}

int main(){
   int t;
   scanf("%d", &t);
   while(t--){
      scanf("%d%d", &n, &m);
      cnt=0;
      memset(first, -1, sizeof(first));
      for(int i=0; i<=n; ++i)
         for(int j=0; j<=n; ++j)
            map[i][j]=INF;
      while(m--){
          int u, v, dist;
          scanf("%d%d%d", &u, &v, &dist);
          if(map[u][v]>dist)
              map[u][v]=map[v][u]=dist;
      }
      for(int i=0; i<=n; ++i)
         for(int j=0; j<=n; ++j)
            if(map[i][j]!=INF)
              addEdge(i, j, map[i][j]); 
      for(int i=1; i<=n; ++i){//最后将1...n节点的最优值汇聚到 第 n+1个节点上 
           edge[cnt++]=EDGE(i, n+1, first[i], 0);
           first[i]=cnt-1;
      }
      sum=0;
      for(int i=1; i<=n; ++i){
         scanf("%d", &w[i]);
         sum+=w[i];
      }
      w[n+1]=0;
      for(int i=0; i<n+2; ++i)
         for(int j=0; j<sum+2; ++j)
            dp[i][j]=INF; 
      spfa();
      int maxCost=INF;
      for(int i=sum/2+1; i<=sum; ++i)
            if(maxCost>dp[n+1][i])
               maxCost=dp[n+1][i];
      if(maxCost==INF)
         printf("impossible\n");
      else printf("%d\n", maxCost);
   }
   return 0;
}

目录
相关文章
|
JavaScript
JS自动生成速记符、拼音简写/拼音的声母(例如:“你挚爱的强哥”转换为“NZADQG”)。提取首字母,返回大写形式;提取拼音, 返回首字母大写形式(全拼)。
JS自动生成速记符、拼音简写/拼音的声母(例如:“你挚爱的强哥”转换为“NZADQG”)。提取首字母,返回大写形式;提取拼音, 返回首字母大写形式(全拼)。
17650 0
|
7月前
|
人工智能 搜索推荐 小程序
时光有节,岁月有气,用 CodeBuddy + 地图 MCP 构建二十四节气
二十四节气作为中国古老智慧的结晶,不仅指导农耕生活,更蕴含深厚文化意义。文章以“小满”为例,解读其象征的生活哲学,并探讨如何借助现代科技如CodeBuddy,将这一传统时间体系融入日常生活。通过制作“二十四节气速查表”,结合天气API和地图功能,让节气焕发新生,成为连接自然与生活的桥梁。这不仅是对文化遗产的传承,更是对传统文化的创新表达。
|
存储 内存技术
内存条RAM详细指南
内存条(RAM)是电脑中用于临时存储数据和程序的部件,CPU依赖它执行操作。内存条经历了从主内存扩展到读写内存整体的发展,常见类型包括SDRAM和DDR SDRAM。内存容量、存取时间和奇偶校验是衡量其性能的关键指标。在选购时,应考虑类型、容量、速度和品牌,知名品牌的内存条提供更好的可靠性和稳定性。
4826 2
|
SQL 存储 缓存
maxcompute的特点
【5月更文挑战第5天】maxcompute的特点
387 6
|
网络协议 物联网 虚拟化
|
Java Python
如何在Python中处理循环引用导致的内存泄漏?
如何在Python中处理循环引用导致的内存泄漏?
287 3
|
移动开发 前端开发 Java
详解WebSocket
详解WebSocket
773 0
|
数据可视化 算法 数据挖掘
JCR一区7.2分|非肿瘤内质网应激切入点,发文不难,非常好复现
这篇研究探讨了内质网应激在扩张型心肌病纤维化中的作用,通过基因综合分析揭示了相关免疫反应。在Apoptosis杂志上发表的文章指出,内质网应激可能与疾病恶化相关,涉及先天和适应性免疫失衡。研究整合了两个数据集,鉴定出103个内质网应激相关基因,其中7个基因可能参与免疫机制。研究结果为理解内质网应激的分子机制和开发新疗法提供了新视角。
281 0
LeetCode】每日一题(4)
LeetCode】每日一题(4)
105 0
|
存储 Java 索引
String和Char的区别
String和Char的区别
1794 1