zoukankan      html  css  js  c++  java
  • 伞兵(Paratroopers)

    伞兵(Paratroopers)

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

    题目描述

    公元 2500 年,地球和火星之间爆发了一场战争。最近,地球军队指挥官获悉火星入侵者将派一些伞兵来摧毁地球的兵工厂,兵工厂是一个 m×n 大小的网格。他还获悉每个伞兵将着陆的具体位置(行和列)。由于火星的伞兵个个都很强壮、而且组织性强,只要有一个伞兵存活了,就能摧毁整个兵工厂。因此,地球军队必须在伞兵着陆后瞬间全部杀死他们。

    为了完成这个任务,地球军队需要利用高科技激光枪。他们能在某行(或某列)安装一架激光枪,一架激光枪能杀死该行(或该列)所有的伞兵。在第 i 行安装一架激光枪的费用是 Ri,在第 i 列安装的费用是 Ci。要安装整个激光枪系统,以便能同时开火,总的费用为这些激光枪费用的乘积。现在,你的任务是选择能杀死所有伞兵的激光枪,并使得整个系统的费用最小。

    输入

    输入文件的第 1 行为整数 T,表示测试数据的数目,接下来有 T 个测试数据。每个测试数据的第 1 行为 3 个整数 m、n 和 L,1≤m≤50,1≤n≤50,1≤L≤500,分别表示网格的行和列、以及伞兵的数目;接下来一行为 m 个大于或等于 1.0 的实数,第 i 个实数表示 Ri;再接下来一行为 n 个大于或等于 1.0 的实数,第 i 个实数表示 Ci;最后 L 行,每行为两个整数,描述了每个伞兵的着陆位置。

    输出

    对每个测试数据,输出搭建整个激光枪系统的最小费用,精确到小数点后面 4 位有效数字。

    样例输入

    1 4 4 5 2.0 7.0 5.0 2.0 1.5 2.0 2.0 8.0 1 1 2 2 3 3 4 4 1 4

    样例输出

    16.0000
    题解:
    首先可以看出这是一道网络流的题目,至于怎么输出所选边的乘积,稍后再说,这里先讲一讲建图。
    1.虚构源点和汇点。
    2.源点和行连边,汇点和列连边。
    3.根据士兵的位置将相对应的行和列连边,权值为正无穷大。
    然后讲一讲怎么输出乘积。
    1.a*b*c=e^(log(a*b*c)) ,又log(a*b*c)=log(a)+log(b)+log(c)
    2.a*b*c最小则log(a)+log(b)+log(c)最小,也就是以log(a),log(b),log(c)为边的图的网络流的最小割。
    3.最大流=最小割,于是乎就成了求log(a),log(b),log(c)为边的图的最大流。
    4.当然最后答案要用exp()还原一下。
    5.完美!!!
    代码仅供参考:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<cstdlib>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<vector>
    using namespace std;
    int n,m,l,t;
    struct node
    {
        int next,to;
        double cap;
    }edge[50001];
    int size=1,head[501];
    void putin(int from,int to,double cap)
    {
        size++;
        edge[size].to=to;
        edge[size].cap=cap;
        edge[size].next=head[from];
        head[from]=size;
    }
    void in(int from,int to,double cap)
    {
        putin(from,to,cap);
        putin(to,from,0);
    }
    int dist[501],numbs[501];
    void bfs(int src,int des)
    {
        int i;
           for(i=0;i<=n+m+1;i++)dist[i]=n+m+2;
        memset(numbs,0,sizeof(numbs));
        queue<int>mem;
        mem.push(des);
        dist[des]=0;numbs[0]++;
        while(!mem.empty())
        {
            int x=mem.front();mem.pop();
            for(i=head[x];i!=-1;i=edge[i].next)
            {
                int y=edge[i].to;
                if(edge[i].cap==0&&dist[y]==n+m+2)
                {
                    dist[y]=dist[x]+1;
                    numbs[dist[y]]++;
                    mem.push(y);
                }
            }
        }
        return;
    }
    double dfs(int src,double flow,int des)
    {
        if(src==des)return flow;
        int i,mindist=n+m+2;
        double low=0;
        for(i=head[src];i!=-1;i=edge[i].next)
        {
            int y=edge[i].to;
            if(edge[i].cap)
            {
                if(dist[y]==dist[src]-1)
                {
                    double t=dfs(y,min(flow-low,edge[i].cap),des);
                    edge[i].cap-=t;
                    edge[i^1].cap+=t;
                    low+=t;
                    if(dist[0]>=n+m+2)return low;
                    if(flow==low)break;
                }
                mindist=min(mindist,dist[y]+1);
            }
        }
        if(!low)
        {
            if(!(--numbs[dist[src]]))dist[0]=n+m+2;
            ++numbs[dist[src]=mindist];
        }
        return low;
    }
    double ISAP(int src,int des)
    {
        double ans=0;
        bfs(src,des);
        while(dist[0]<n+m+2)ans+=dfs(src,2e8,des);
        return ans;
    }
    int main()
    {
        int i,j;
        scanf("%d",&t);
        while(t--)
        {
            size=1;
            memset(head,-1,sizeof(head));
            scanf("%d%d%d",&n,&m,&l);
            for(i=1;i<=n;i++)
            {
                double q;
                scanf("%lf",&q);
                in(0,i,log(q));
            }
            for(i=1;i<=m;i++)
            {
                double q;
                scanf("%lf",&q);
                in(n+i,n+m+1,log(q));
            }
            for(i=1;i<=l;i++)
            {
                int from,to;
                scanf("%d%d",&from,&to);
                in(from,n+to,100000000);
            }
            double maxflow=ISAP(0,n+m+1);
            printf("%.4lf
    ",exp(maxflow));
        }
        return 0;
    }
  • 相关阅读:
    [原创]Java在线编辑word文档调用PageOffice实现并发控制
    [原创]Java动态填充word文档并上传到服务器
    mysql数据类型
    mysql 数据增删改查基本语句
    MYSQL中char 与 varchar 的区别
    MYSQL 同时执行多条SQL语句
    关于MyEclipse10编辑JSP卡顿现象
    鼠标悬停放大图片效果
    简单实现 飘浮 广告层特效
    简单实现 特效(董侨JonneyDong)
  • 原文地址:https://www.cnblogs.com/huangdalaofighting/p/6885871.html
Copyright © 2011-2022 走看看