hdu 3931 Cross the Fire

来源:互联网 发布:linux python ssh模块 编辑:程序博客网 时间:2024/05/22 10:49

Cross the Fire

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 84    Accepted Submission(s): 43


Problem Description
Our hero is planned to cross an important street, the other side of the street is the headquarters of the enemy. The whole street is a rectangle with length L and width W. Because the streets are sealed of the building block on both up and down side, we assumed people can only walk down on the street but not get out the up and down board.
In order to prevent our hero, the evil enemy layout N mines in the street. Due to internal staff informed in advance, the hero has known the distribution of all mines, and their explosion radius and explosion power. The mine enemy used is an amazing sense-mine, as long as the person come into its sensing radius, it will explode, due to unknown reasons, the explosion radius of each mine is same to its sensing radius. Heroes have a certain strength value at first, but once he touching a mine, he will lose some strength value same to the explosion power of this mine. Once the hero's strength value is not greater than zero, he will die.
Now hero want you to help him calculate whether there is a path so that he can live to reach the enemy headquarters. If he can live to cross the street, he wants to know the maximum remaining strength value after crossing the street. We assume the hero's path trajectory is arbitrary.
 

Input
The input consists of several test cases.
The first line contains four integers L, W, N and P– the length and the width of the street, the number of mines, and the initial strength value of hero, respectively(1 ≤ L ≤ 10000 ,1 ≤ W ≤ 10000, 1 ≤ N ≤ 250, 1 ≤ P ≤ 1000000). Each of the following N lines contains four integers Xi, Yi, Ri and Pi – the coordinates, the sensing radius(explosion radius) and the explosion power of i-th mine in the street (0 ≤ Xi ≤ L, 0 ≤ Yi ≤ W, 1 ≤ Ri ≤ 100, 1 ≤ Pi ≤ 10000). The coordinates and radius are given in meters, relative to the street: the southwestern corner of the street has coordinates (0, 0), and the northeastern corner of the street has coordinates (L, W).
Note that crossing the street may start at coordinate (0, ys ) for any 0 ≤ ys ≤ W and end at coordinate (L, ye ) for any 0 ≤ ye ≤ W . Neither ys nor ye need to be integer.
 

Output
For each input cases, if our hero cannot live to cross the street, please output “Our hero has been killed”; otherwise output the maximum remaining strength value after crossing the street.
 

Sample Input
130 340 5 210 50 100 1130 130 100 170 170 100 10 180 100 160 260 100 1
 

Sample Output
1
 
赛后解题报告:
这道题显然不是一道计算几何。
我们可以思考人必须触雷的情况,它只会发生在有一群雷相互连接并且封锁了上下边界的情况下。
我们将所有的圆映射成无向图上的点,并且把任意两个相交的圆(包括相切和包含)之间连上一条无向边;将上边界当成逻辑源点,下边界当成逻辑汇点,所有与之相交的圆都分别向它们连上一条有向边。
模型抽象为若存在一条从源点到汇点的独立轨,则人必须触一次雷,而人想通过街道,意味着要破坏这些独立轨,使得源点和汇点之间失去连通性。
这个显然是一个无向图的最小权点割问题了。
将除了源汇点之外的内点全部拆点,原来的点权转化为边容量,其它边的边容量为正无穷,接着从源点向汇点压流。
最后比较一下最大流值和人的初始体力值即是最后的答案。
 
 
 
 
#include <iostream>#include <set>#include <cmath>using namespace std;const int N=1005;const int inf=0x3f3f3f3f;struct circle{int x,y,r;}a[N];struct rec{    int v,w,link;}edge[50500];int head[N],cur[N],dis[N],gap[N],val[N],pre[N];int n,m,st,ed,num,P,L,W;double Dis(circle a,circle b){double x=a.x-b.x;double y=a.y-b.y;return sqrt(x*x+y*y);}void addedge(int u,int v,int w){    edge[num].v=v;    edge[num].w=w;    edge[num].link=head[u];    head[u]=num++;    edge[num].v=u;    edge[num].w=0;    edge[num].link=head[v];    head[v]=num++;}int SAP(){    int i,u,v,mindis,aug=inf,ans=0;    memset(dis,0,sizeof(dis));    memset(gap,0,sizeof(gap));    for(i=1;i<=ed;i++)        cur[i]=head[i];    gap[0]=ed;    u=pre[st]=st;    while(dis[st]<ed)    {loop:    for(i=cur[u];i;i=cur[u]=edge[i].link)        {            v=edge[i].v;            if(edge[i].w && dis[u]==dis[v]+1)            {                pre[v]=u;                u=v;                if(aug>edge[i].w)                    aug=edge[i].w;                if(u==ed)                {                    for(u=pre[u];v!=st;v=u,u=pre[u])                    {                        edge[cur[u]].w-=aug;                        edge[cur[u]^1].w+=aug;                    }                    ans+=aug;                    aug=inf;                }                goto loop;            }        }        mindis=ed;        for(i=head[u];i;i=edge[i].link)        {            v=edge[i].v;            if(edge[i].w && mindis>dis[v])            {                mindis=dis[v];                cur[u]=i;            }        }        if(--gap[dis[u]]==0)            break;        gap[dis[u]=mindis+1]++;        u=pre[u];    }    return ans;}int main(){int i,j,k,w;while(~scanf("%d%d%d%d",&L,&W,&n,&P)){st=2*n+1;ed=2*n+2;num=2;memset(head,0,sizeof(head));for(i=1;i<=n;i++){scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].r,&w);addedge(i,i+n,w);if(W-a[i].y<=a[i].r)addedge(st,i,inf);if(a[i].y<=a[i].r)addedge(i+n,ed,inf);}for(i=1;i<n;i++)for(j=i+1;j<=n;j++)if(Dis(a[i],a[j])<=a[i].r+a[j].r){addedge(i+n,j,inf);addedge(j+n,i,inf);}k=SAP();if(k>=P)puts("Our hero has been killed");elseprintf("%d\n",P-k);}return 0;}