zoukankan      html  css  js  c++  java
  • 题解 最优的挤奶方案(Optimal Milking)

    最优的挤奶方案(Optimal Milking)

    时间限制: 1 Sec  内存限制: 128 MB

    题目描述

    农场主 John 将他的 K(1≤K≤30)个挤奶器运到牧场,在那里有 C(1≤C≤200)头奶牛,在奶
    牛和挤奶器之间有一组不同长度的路。K个挤奶器的位置用1~K的编号标明,奶牛的位置用K+1~
    K+C 的编号标明。
    每台挤奶器每天最多能为 M(1≤M≤15)头奶牛挤奶。
    编写程序,寻找一个方案,安排每头奶牛到某个挤奶器挤奶,并使得 C 头奶牛需要走的所有
    路程中的最大路程最小。每个测试数据中至少有一个安排方案。每条奶牛到挤奶器有多条路。

    输入

    第 1 行为 3 个整数 K、C 和 M。
    第 2~K+C+1 行,每行有 K+C 个整数,描述了奶牛和挤奶器(二者合称实体)之间的位置,
    这 K+C 行构成了一个沿对角线对称的矩阵。第 2 行描述了第 1 个挤奶器离其他实体的距离,…,
    第 K+1 行描述了第 K 个挤奶器离其他实体的距离;第 K+2 行描述了第 1 头奶牛离其他实体的距
    离,…。这些距离为不超过 200 的正数。实体之间如果没有直接路径相连,则距离为 0。实体与
    本身的距离(即对角线上的整数)也为 0。

    输出

    输出一个整数,为所有方案中,C 头奶牛需要走的最大距离的最小值。
     

    样例输入

    2 3 2
    0 3 2 1 1
    3 0 3 2 0
    2 3 0 1 0
    1 2 1 0 2
    1 0 0 2 0

    样例输出

    2
    题解:
    又是一道网络流套二分的题目。
    1.先用floyd求一个最短路map。
    2.每一次虚拟一个源点和挤奶器建边,虚拟一个汇点和奶牛建边。
    3.Dinic跑起来!!!
    4.然后。。。就没有然后了。。。
    AC代码:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<vector>
    using namespace std;
    int n,m,l,s;
    int map[301][301],cap[301][301],depth[301];
    int read()
    {
        int ans=0,f=1;
        char i=getchar();
        while(i<'0'||i>'9'){if(i=='-')f=-1;i=getchar();}
        while(i>='0'&&i<='9'){ans=ans*10+i-'0';i=getchar();}
        return ans*f;
    }
    bool bfs()
    {
        memset(depth,0,sizeof(depth));
        int b[30001],head=0,tail=0,i;
        b[tail++]=0;
        depth[0]=1;
        while(head!=tail)
        {
            int x=b[head++];
            for(i=0; i<=s+1; i++)
            {
                if(depth[i]==0&&cap[x][i]>0)
                {
                    depth[i]=depth[x]+1;
                    b[tail++]=i;
                }
            }
        }
        if(depth[s+1]!=0)return 1;
        else return 0;
    }
    int dfs(int root,int flow)
    {
        if(root==s+1)return flow;
        int res=0;
        for(int i=0; i<=s+1; i++)
        {
            if(cap[root][i]>0&&depth[i]==depth[root]+1)
            {
                int tmp=dfs(i,min(flow-res,cap[root][i]));
                cap[root][i]-=tmp;
                cap[i][root]+=tmp;
                res+=tmp;
                if(res==flow)return flow;
            }
        }
        return res;
    }
    bool judge(int mid)
    {
        memset(cap,0,sizeof(cap));
        int i,j,k;
        for(i=1; i<=n; i++)
            cap[0][i]=l;
        for(i=1; i<=n; i++)
            for(j=n+1; j<=s; j++)
                if(map[i][j]<=mid)
                    cap[i][j]=1;
        for(i=n+1; i<=s; i++)
            cap[i][s+1]=1;
        int root=0,f=0;
        while(bfs())
        {
            f+=dfs(root,2000000000);
        }
        return f>=m;
    }
    int main()
    {
        int i,j,k;
        n=read();
        m=read();
        l=read();
        s=n+m;
        for(i=1; i<=s; i++)
            for(j=1; j<=s; j++)
            {
                map[i][j]=read();
                if(map[i][j]==0)map[i][j]=2e8;
            }
        for(k=1; k<=s; k++)
            for(i=1; i<=s; i++)
                for(j=1; j<=s; j++)
                    if(i!=j&&j!=k&&k!=i&&map[i][k]+map[k][j]<map[i][j])
                        map[i][j]=map[i][k]+map[k][j];
        int l=0,r=5000000,ans=5000000;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(judge(mid))
            {
                ans=mid;
                r=mid-1;
            }
            else l=mid+1;
        }
        printf("%d
    ",ans);
        return 0;
    }

    总结:

    1.最大值不能赋太大,否则会溢出。

    2.最好还是用非递归的Dinic。

  • 相关阅读:
    94. Binary Tree Inorder Traversal
    101. Symmetric Tree
    38. Count and Say
    28. Implement strStr()
    实训团队心得(1)
    探索性测试入门
    LC.278. First Bad Version
    Search in Unknown Sized Sorted Array
    LC.88. Merge Sorted Array
    LC.283.Move Zeroes
  • 原文地址:https://www.cnblogs.com/huangdalaofighting/p/6830413.html
Copyright © 2011-2022 走看看