伞兵(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[];
int size=,head[];
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,);
}
int dist[],numbs[];
void bfs(int src,int des)
{
int i;
for(i=;i<=n+m+;i++)dist[i]=n+m+;
memset(numbs,,sizeof(numbs));
queue<int>mem;
mem.push(des);
dist[des]=;numbs[]++;
while(!mem.empty())
{
int x=mem.front();mem.pop();
for(i=head[x];i!=-;i=edge[i].next)
{
int y=edge[i].to;
if(edge[i].cap==&&dist[y]==n+m+)
{
dist[y]=dist[x]+;
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+;
double low=;
for(i=head[src];i!=-;i=edge[i].next)
{
int y=edge[i].to;
if(edge[i].cap)
{
if(dist[y]==dist[src]-)
{
double t=dfs(y,min(flow-low,edge[i].cap),des);
edge[i].cap-=t;
edge[i^].cap+=t;
low+=t;
if(dist[]>=n+m+)return low;
if(flow==low)break;
}
mindist=min(mindist,dist[y]+);
}
}
if(!low)
{
if(!(--numbs[dist[src]]))dist[]=n+m+;
++numbs[dist[src]=mindist];
}
return low;
}
double ISAP(int src,int des)
{
double ans=;
bfs(src,des);
while(dist[]<n+m+)ans+=dfs(src,2e8,des);
return ans;
}
int main()
{
int i,j;
scanf("%d",&t);
while(t--)
{
size=;
memset(head,-,sizeof(head));
scanf("%d%d%d",&n,&m,&l);
for(i=;i<=n;i++)
{
double q;
scanf("%lf",&q);
in(,i,log(q));
}
for(i=;i<=m;i++)
{
double q;
scanf("%lf",&q);
in(n+i,n+m+,log(q));
}
for(i=;i<=l;i++)
{
int from,to;
scanf("%d%d",&from,&to);
in(from,n+to,);
}
double maxflow=ISAP(,n+m+);
printf("%.4lf\n",exp(maxflow));
}
return ;
}

伞兵(Paratroopers)的更多相关文章

  1. POJ 3308 Paratroopers(最小割EK(邻接表&矩阵))

    Description It is year 2500 A.D. and there is a terrible war between the forces of the Earth and the ...

  2. POJ - 3308 Paratroopers(最大流)

    1.这道题学了个单词,product 还有 乘积 的意思.. 题意就是在一个 m*n的矩阵中,放入L个敌军的伞兵,而我军要在伞兵落地的瞬间将其消灭.现在我军用一种激光枪组建一个防御系统,这种枪可以安装 ...

  3. ACM/ICPC 之 伞兵-最小割转最大流(POJ3308)

    //以行列建点,伞兵位置为单向边-利用对数将乘积转加法 //最小割转最大流 //Time:63Ms Memory:792K #include<iostream> #include<c ...

  4. Paratroopers

    Paratroopers Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7881 Accepted: 2373 Descript ...

  5. POJ3308 Paratroopers(网络流)(最小割)

                                                     Paratroopers Time Limit: 1000MS   Memory Limit: 655 ...

  6. POJ 3308 Paratroopers(最小割EK)

    题目链接 题意 : 有一个n*m的矩阵,L个伞兵可能落在某些点上,这些点的坐标已知,需要在某些位置安上一些枪,然后每个枪可以将一行或者一列的伞兵击毙.把这种枪安装到不同行的行首.或者不同列的列首,费用 ...

  7. zoj 2874 &amp; poj 3308 Paratroopers (最小割)

    意甲冠军: 一m*n该网络的规模格.详细地点称为伞兵着陆(行和列). 现在,在一排(或列) 安装激光枪,激光枪可以杀死线(或塔)所有伞兵.在第一i安装一排 费用是Ri.在第i列安装的费用是Ci. 要安 ...

  8. POJ 3308 Paratroopers 最大流,乘积化和 难度:2

    Paratroopers Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7267   Accepted: 2194 Desc ...

  9. POJ 3308 Paratroopers(最小点权覆盖)(对数乘转加)

    http://poj.org/problem?id=3308 r*c的地图 每一个大炮可以消灭一行一列的敌人 安装消灭第i行的大炮花费是ri 安装消灭第j行的大炮花费是ci 已知敌人坐标,同时消灭所有 ...

随机推荐

  1. css写出三角形(兼容IE)

    css写出三角形   利用css写三角形,兼容IE7 .arrow-up { width:0px; height:0px; border-left:10px solid transparent; bo ...

  2. mysql的一些使用操作

    1:如果空闲时间很长导致mysql报错: Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last pa ...

  3. Android Weekly Notes Issue #256

    Android Weekly Issue #256 May 7th, 2017 Android Weekly Issue #256 本期内容包括: 一个给ViewPager切换时加动画的库; Tail ...

  4. 单页应用跳转ui-view,$stateProvider,$urlRouterProvider

    <!DOCTYPE HTML> <html ng-app="myApp"> <head> <meta charset="UTF- ...

  5. ReactiveCocoa学习总结(1)

    1. 它是什么? 官方解释: [RACSignal] is a push-driven stream with a focus on asynchronous event delivery throu ...

  6. 非阻塞式线程安全列表-ConcurrentLinkedDeque

    一.ConcurrentLinkedDeque public class ConcurrentLinkedDeque<E> extends AbstractCollection<E& ...

  7. smarty的学习计划(2)

    连接数据库时,处理数据用原生态的PHP函数???NO,我们用phplib里的DB类,它文件小.加载速度快而备受人们喜爱. copy一个目录表: web(站点根目录) |-----libs(Smarty ...

  8. Hibernate笔记一:HIbernate配置-HelloWorld

    hibernate介绍: Hibernate是一个开源的对象关系映射框架,它对JDBC进行了轻量级的对象封装,使Java程序员可以随心所欲的使用对象编程思维来操纵数据库. 它不仅提供了从java类到数 ...

  9. PHP简单分页省略中间页码

    <?php /** * @desc created by sublime text3 * @author jxl <[57953279@qq.com>]> * @since 2 ...

  10. Reverse Integer 2015年6月23日

    题目: Reverse digits of an integer. Example1: x = , return Example2: x = -, return - 思路:递归 解答: / test ...