码迷,mamicode.com
首页 > 其他好文 > 详细

【bzoj1066】[SCOI2007]蜥蜴 网络最大流

时间:2015-08-16 11:59:23      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:

【bzoj1066】[SCOI2007]蜥蜴

Description

在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。

Input

输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石竹的初始状态,0表示没有石柱,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。

Output

输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。

Sample Input

5 8 2
00000000
02000000
00321100
02000000
00000000
……..
……..
..LLLL..
……..
……..

Sample Output

1

HINT

 

100%的数据满足:1<=r, c<=20, 1<=d<=3

 

代码

对于每根石柱,采取一分为二的想法,即把一个点分为两个点(可抽象为石柱底部到顶部),其连线容量限制为石柱高度。

超级源与所有有蜥蜴的点相连,容量为1。

超级汇与地图内所有能跳出的点的底端相连,容量为INF。

对于地图内任意两个石柱,如果间距小于d,就将其中一根石柱的底部与另一根石柱的顶部相连,其连线容量为INF。

构图完成,剩下就是跑一遍最大流,然后用蜥蜴数量减去最大流就是最终结果。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <typeinfo>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
inline ll read()
{
    ll x=0,f=1;
    char ch=getchar();
    while(ch<0||ch>9)
    {
        if(ch==-)f=-1;
        ch=getchar();
    }
    while(ch>=0&&ch<=9)
    {
        x=x*10+ch-0;
        ch=getchar();
    }
    return x*f;
}
//***************************
namespace NetFlow
{
const int MAXN=100000,MAXM=500000,inf=1e9;
struct Edge
{
    int v,c,f,nx;
    Edge() {}
    Edge(int v,int c,int f,int nx):v(v),c(c),f(f),nx(nx) {}
} E[MAXM];
int G[MAXN],cur[MAXN],pre[MAXN],dis[MAXN],gap[MAXN],N,sz;
void init(int _n)
{
    N=_n,sz=0;
    memset(G,-1,sizeof(G[0])*N);
}
void link(int u,int v,int c)
{
    E[sz]=Edge(v,c,0,G[u]);
    G[u]=sz++;
    E[sz]=Edge(u,0,0,G[v]);
    G[v]=sz++;
}
int ISAP(int S,int T)
{
    //S -> T
    int maxflow=0,aug=inf,flag=false,u,v;
    for (int i=0; i<N; ++i)cur[i]=G[i],gap[i]=dis[i]=0;
    for (gap[S]=N,u=pre[S]=S; dis[S]<N; flag=false)
    {
        for (int &it=cur[u]; ~it; it=E[it].nx)
        {
            if (E[it].c>E[it].f&&dis[u]==dis[v=E[it].v]+1)
            {
                if (aug>E[it].c-E[it].f) aug=E[it].c-E[it].f;
                pre[v]=u,u=v;
                flag=true;
                if (u==T)
                {
                    for (maxflow+=aug; u!=S;)
                    {
                        E[cur[u=pre[u]]].f+=aug;
                        E[cur[u]^1].f-=aug;
                    }
                    aug=inf;
                }
                break;
            }
        }
        if (flag) continue;
        int mx=N;
        for (int it=G[u]; ~it; it=E[it].nx)
        {
            if (E[it].c>E[it].f&&dis[E[it].v]<mx)
            {
                mx=dis[E[it].v];
                cur[u]=it;
            }
        }
        if ((--gap[dis[u]])==0) break;
        ++gap[dis[u]=mx+1];
        u=pre[u];
    }
    return maxflow;
}
bool bfs(int S,int T)
{
    static int Q[MAXN];
    memset(dis,-1,sizeof(dis[0])*N);
    dis[S]=0;
    Q[0]=S;
    for (int h=0,t=1,u,v,it; h<t; ++h)
    {
        for (u=Q[h],it=G[u]; ~it; it=E[it].nx)
        {
            if (dis[v=E[it].v]==-1&&E[it].c>E[it].f)
            {
                dis[v]=dis[u]+1;
                Q[t++]=v;
            }
        }
    }
    return dis[T]!=-1;
}
int dfs(int u,int T,int low)
{
    if (u==T) return low;
    int ret=0,tmp,v;
    for (int &it=cur[u]; ~it&&ret<low; it=E[it].nx)
    {
        if (dis[v=E[it].v]==dis[u]+1&&E[it].c>E[it].f)
        {
            if (tmp=dfs(v,T,min(low-ret,E[it].c-E[it].f)))
            {
                ret+=tmp;
                E[it].f+=tmp;
                E[it^1].f-=tmp;
            }
        }
    }
    if (!ret) dis[u]=-1;
    return ret;
}
int dinic(int S,int T)
{
    int maxflow=0,tmp;
    while (bfs(S,T))
    {
        memcpy(cur,G,sizeof(G[0])*N);
        while (tmp=dfs(S,T,inf)) maxflow+=tmp;
    }
    return maxflow;
}
}
using namespace NetFlow;
double dist(int a,int b,int x,int y)
{
    return sqrt((b-y)*(b-y)+(a-x)*(a-x));
}
int  main()
{
    int n,m,d;
    char mp[33][33],mp2[33][33];
    cin>>n>>m>>d;
    init(1500);
    for(int i=1; i<=n; i++)
    {
        scanf("%s",mp[i]+1);
    }
    for(int i=1; i<=n; i++)
    {
        scanf("%s",mp2[i]+1);
    }
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            if((mp[i][j]-0)>0)
            {
                for(int h=i-d; h<=i+d; h++)
                {
                    for(int k=j-d; k<=j+d; k++)
                    {
                        if(h==i&&j==k)continue;
                        if(h<0||k<0||h>n+1||k>m+1)
                            continue;
                        double dd=d*1.0;
                        if(dist(i,j,h,k)>dd)continue;
                        if(h==0||k==0||h==n+1||k==m+1)
                            link((i-1)*m+j+400,1000,inf);
                        else  link((i-1)*m+j+400,(h-1)*m+k,inf);
                    }
                }
                link((i-1)*m+j,(i-1)*m+j+400,mp[i][j]-0);
            }

        }
    }
    int sum=0;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            if(mp2[i][j]==L)
            {
                sum++;
                link(999,(i-1)*m+j,1);
            }
        }
    }
    cout<<sum-dinic(999,1000)<<endl;
    return 0;
}

 

【bzoj1066】[SCOI2007]蜥蜴 网络最大流

标签:

原文地址:http://www.cnblogs.com/zxhl/p/4733726.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!