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;
    }
  • 相关阅读:
    ImportError: Matplotlib qt-based backends require an external PyQt4, PyQt5, PySide or PySide2 package to be installed, but it was not found.
    cannot load library 'libportaudio.so.2': libportaudio.so.2: cannot open shared object file: No such file or directory
    如何解决Linux系统下pyaudio安装缺少文件问题error: portaudio.h: 没有那个文件或目录
    完美解决 python ImportError: Failed to import any qt binding
    Linux傻瓜式四步完美安装Python3.7
    为什么诺贝尔奖得主很少有中国人?
    Web前端入门知识
    MySQL通用编程
    其实我想做个诗人
    八皇后问题Python实现
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9995175.html
Copyright © 2011-2022 走看看