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

    题目描述:

    W 教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业性实验而获取利润。

    现已确定了一个可供选择的实验集合E= {E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={I1,I2,…In}。

    实验Ej需要用到的仪器是I的子集RjÍI。配置仪器 Ik的费用为ck美元。

    实验Ej的赞助商已同意为该实验结果支付pj美元。W教授的任务是找出一个有效算法,确定在一次太空飞行中要进行哪些实验并因此而 配置哪些仪器才能使太空飞行的净收益最大。

    这里净收益是指进行实验所获得的全部收入与配置仪器的全部费用的差额。

    对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。

    题解:

    将问题抽象成一个图:(S源点,T汇点)

    1.S->所有实验,边权为实验收入;

    2.所有器材->T,边权为器材花费;

    3.实验->器材,边权inf。

    然后(所有收入-最大流)就是最终答案。

    原因?

    最大流=最小割。

    (割掉==买)

    首先求出的最小割一定不包含inf的边……

    然后,

    比如割在(器材->T)的边上,那么相当于相关实验的收入可以覆盖这个器材的花费。可以割掉。

    在比如说割在(S->实验)的边上,相当于做实验的钱都花在器材身上。

    真实收入+=实验,真实花费+=实验。

    所以做差之后结果没变。

    所以算法是正确的。

    还有判断器材:

    枚举删(器材->T)的边,如果删后最大流==最大流-边权,那么就用这个器材。

    判断实验很简单就不说了。

    具体实现:

    加边,然后一直跑最大流(我用的dinic)。

    代码:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 55
    #define ll long long
    inline int rd()
    {
        int f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
        return f*c;
    }
    int n,m,S,T,hed[N<<1],cnt=-1;
    const int inf = 0x3f3f3f3f;
    struct EG
    {
        int to,nxt;
        int vl;
    }E[N*N*2],e[N*N*2];
    void ae(int f,int t,int v)
    {
        E[++cnt].to = t;
        E[cnt].nxt = hed[f];
        E[cnt].vl = v;
        hed[f] = cnt;
    }
    int dep[N<<1],cur[N<<1];
    bool bfs(int ban)
    {
        queue<int>q;
        memset(dep,0x3f,sizeof(dep));
        memcpy(cur,hed,sizeof(cur));
        dep[S]=0;
        q.push(S);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            for(int j=hed[u];~j;j=e[j].nxt)
            {
                int to = e[j].to;
                if(j==ban)continue;
                if(e[j].vl&&dep[to]==inf)
                {
                    dep[to]=dep[u]+1;
                    q.push(to);
                }
            }
        }
        if(dep[T]!=inf)return 1;
        return 0;
    }
    int dfs(int u,int lim,int ban)
    {
        if(!lim||u==T)return lim;
        int fl=0,f;
        for(int j=cur[u];~j;j=e[j].nxt)
        {
            cur[u]=j;
            int to = e[j].to;
            if(j==ban)continue;
            if(dep[to]==dep[u]+1&&(f=dfs(to,min(lim,e[j].vl),ban)))
            {
                fl+=f;
                lim-=f;
                e[j].vl-=f;
                e[j^1].vl+=f;
                if(!lim)break;
            }
        }
        return fl;
    }
    int dinic(int ban)
    {
        int ret = 0;
        memcpy(e,E,sizeof(e));
        while(bfs(ban))
            ret+=dfs(S,inf,ban);
        return ret;
    }
    bool use[N];
    
    int main()
    {
        m=rd(),n=rd();
        S=0,T=n+m+1;
        memset(hed,-1,sizeof(hed));
        int sum = 0;
        for(int x,i=1;i<=m;i++)
        {
            x=rd();
            ae(S,i,x);
            ae(i,S,0);
            sum+=x;
            char c=getchar();
            x=0;
            while(c!='
    '&&c!='
    ')
            {
                if(c==' '&&x)
                {
                    ae(i,x+m,inf);
                    ae(x+m,i,0);
                    x=0;
                    c=getchar();
                    continue;
                }
                x=x*10+c-'0';
                c=getchar();
            }
            if(x)
            {
                ae(i,x+m,inf);
                ae(x+m,i,0);
            }
        }
        for(int x,i=1;i<=n;i++)
        {
            x=rd();
            ae(i+m,T,x);
            ae(T,i+m,0);
        }
        int ans = dinic(-1);
        for(int i=m+1;i<=m+n;i++)
        {
            for(int j=hed[i];~j;j=E[j].nxt)
            {
                int to = E[j].to;
                if(to==T)
                {
                    int tmp = dinic(j);
                    if(tmp+E[j].vl==ans)use[i-m]=1;
                    break;
                }
            }
        }
        for(int i=1;i<=m;i++)
        {
            bool g = 1;
            for(int j=hed[i];~j;j=E[j].nxt)
            {
                int to = E[j].to;
                if(to!=S&&!use[to-m])
                {
                    g=0;
                    break;
                }
            }
            if(g)printf("%d ",i);
        }
        printf("
    ");
        for(int i=1;i<=n;i++)
            if(use[i])
                printf("%d ",i);
        printf("
    %d
    ",sum-ans);
        return 0;
    }
  • 相关阅读:
    TCP/IP学习笔记(3)-IP、ARP、RARP协议
    TCP/IP学习笔记(2)-数据链路层
    tcp/ip学习笔记(1)-基本概念
    实体bean里面不要轻易加transient,反序列回来之后会变成null
    [Maven实战-许晓斌]-[第三章] Mave使用入门二(在IDE中的使用) [第四章] 案例的背景介绍
    [Maven实战-许晓斌]-[第三章] Mave使用入门
    [Maven实战-许晓斌]-[第二章]-2.7-2.8 Mave安装的最优建议和安装小结
    [Maven实战-许晓斌]-[第二章]-2.6 NetBeans上面安装Maven插件
    ifdown
    ifup
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9995175.html
Copyright © 2011-2022 走看看