zoukankan      html  css  js  c++  java
  • 太空飞行计划问题

    W 教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业
    性实验而获取利润。现已确定了一个可供选择的实验集合 E={E1,E2,…,Em},和进行这
    些实验需要使用的全部仪器的集合I={I1, I2,…In}。 实验 Ej需要用到的仪器是 I的子集 RjÍI。
    配置仪器Ik的费用为Ck美元。实验Ej的赞助商已同意为该实验结果支付Pj美元。W教授的
    任务是找出一个有效算法, 确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才
    能使太空飞行的净收益最大。这里净收益是指进行实验所获得的全部收入与配置仪器的全部
    费用的差额。 
    ´编程任务: 
    对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。

    Input

    第 1行有 2 个正整数 m和 n。m是实验数,n是仪
    器数。接下来的 m 行,每行是一个实验的有关数据。第一个数赞助商同意支付该实验的费
    用;接着是该实验需要用到的若干仪器的编号。最后一行的 n个数是配置每个仪器的费用。 

    Output

    程序运行结束时,将最佳实验方案输出。第 1 行是实验编号;第 2
    行是仪器编号;最后一行是净收益。
    -----------------------------------------------------------------------------------
    正解=网络流
    设Sum为金钱和
    题目所求相当于 求Sum(所做实验)-Sum(所需仪器)
    既 Total(所有实验)-Sum(不做的实验)-Sum(所需仪器)
    所以只需求出 Sum(不做的实验)+Sum(所需仪器)的最小值
    考虑网络流:
    构图:
      将 实验Xi 于 仪器Yi 分成2个集合
      若实验 Xi 需要 仪器Yj 则在 i j 间连一条流量为无限的边
      将 源点S 连向所有实验流量为实验利润
      将所有仪器连向 汇点T 流量为运输费用
    证明:
      考虑一个仪器对应一个实验
        割仪器表示所这个实验应减掉仪器的钱
        割实验表示不做这个实验应减掉这个实验的钱
      - =
    如果一个实验要做则它所需的仪器都应属于Sum(所需仪器)
    既当Xi存在网络中时它所需的仪器都不能存在于网络中
    既不存在从 S 到 T 的流为合法情况
    且需要Sum(不做的实验)+Sum(所需仪器)最小
    既求最小割- =
    代码如下:
     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<string>
     4 #include<cstring>
     5 #include<iostream>
     6 #include<cmath>
     7 #define LL long long
     8 #define INF 999999999
     9 #define Min(num1,num2) if(num1>num2) num1=num2
    10 #define Max(num1,num2) if(num1<num2) num1=num2
    11 #define N 100100
    12 //using namespace std ;
    13 int next[N],last[N],flow[N],to[N],op[N],G;
    14 int Total,n,m,ans,nodes,S,T,dis[N],cnt[N];
    15 bool vis[N];
    16 void addedge(int x,int y,int v){
    17     next[++G]=last[x]; last[x]=G; flow[G]=v; to[G]=y; op[G]=G+1;
    18     next[++G]=last[y]; last[y]=G; flow[G]=0; to[G]=x; op[G]=G-1;    
    19 }
    20 int sap(int t,int delta){
    21     if(t==T) return delta;
    22     int sum=0,mindis=nodes;
    23     for(int i=last[t]; i ;i=next[i]){
    24         if(flow[i]>0 && dis[to[i]]+1==dis[t]){
    25             int save = sap(to[i],std::min(flow[i],delta-sum));
    26             sum += save;
    27             flow[   i ] -= save;
    28             flow[op[i]] += save;
    29             if (dis[S]>=nodes||sum==delta) return sum;
    30         }    
    31         if(flow[i]>0)    Min(mindis,dis[to[i]]);
    32     }
    33     if(sum==0){
    34         if(!--cnt[dis[t]]) dis[S]=nodes;
    35         else ++cnt[dis[t]=mindis+1];
    36     }
    37     return sum;
    38 }
    39 void DFS(int t){
    40     for(int i=last[t];i;i=next[i])
    41         if(!vis[to[i]]&&flow[i]){
    42             vis[to[i]]=1;
    43             DFS(to[i]);
    44         }
    45 }
    46 int main(){
    47   scanf("%d%d",&m,&n);
    48   S=0;
    49   T=m+n+1;
    50     for(int x,y,i=1;i<=m;i++){
    51         char flag;
    52         scanf("%d%c",&x,&flag);
    53       addedge(S,i,x);
    54       Total+=x;
    55         while(flag!='
    '){
    56             scanf("%d%c",&y,&flag);
    57           addedge(i,y+m,INF);
    58         }
    59     }
    60     for(int x,i=1;i<=n;i++){
    61         scanf("%d",&x);
    62         addedge(i+m,T,x);
    63     }
    64     nodes=cnt[0]=T+1;
    65     while(nodes>dis[S]) ans+=sap(S,INF);
    66     DFS(S);
    67     bool use=false ;
    68     for(int i=1;i<=m;i++)
    69         if(vis[i]){
    70             if(use) printf(" ");
    71             printf("%d",i);
    72             use=1;
    73         }
    74     use=false ;
    75     printf("
    ");
    76     for(int i=m+1;i<=n+m;i++) 
    77         if(vis[i]){
    78             if(use) printf(" ");
    79             printf("%d",i-m);
    80             use=1;
    81         }
    82     printf("
    %d",Total-ans);
    83 }
    View Code
  • 相关阅读:
    Supported orientations has no common orientation with the application, and [UIAlertController shouldAutorotate] is returning YES
    软件工程学习进度第一周暨暑期学习进度之第一周汇总
    软件分享大会之Bonny使用感想
    ios开发的技巧
    Xcode修改项目名称
    ios--NavigationViewController跳转、返回传值
    数组的重复排序
    判断时间差
    比较全的表单提交页面对电话邮箱判断
    coreData的使用
  • 原文地址:https://www.cnblogs.com/Blacko/p/3433901.html
Copyright © 2011-2022 走看看