bzoj1066: [SCOI2007]蜥蜴

http://www.lydsy.com/JudgeOnline/problem.php?id=1066

 

每个柱子拆成两个点 i<<1,i<<1|1,之间连流量为高度的边

如果第i根柱子有蜥蜴,S向i<<1连边,流量为1

如果第i根柱子能跳出去,i<<1|1向T连边,流量为inf

如果第i根柱子能跳到第j根柱子,i<<1|1向j<<1连边,流量为inf

至于每根柱子每个时刻只能有一个蜥蜴,不需要管,总可以通过先后顺序调整成满足条件

 

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

#define N 900
#define M 21500

const int inf=1e9;

char s[21];
int mp[21][21];

int cnt;
int id[21][21];

int tot=1;
int front[N],nxt[M<<1],to[M<<1],val[M<<1],from[M<<1];
int lev[N],num[N];
int path[N];
int cur[N];
 
int src,decc;

void add(int u,int v,int w)
{
    to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; from[tot]=u; val[tot]=w;
    to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; from[tot]=v; val[tot]=0;
    //cout<<u<<' '<<v<<' '<<w<<'\n';
}

bool bfs()
{
    queue<int>q;
    for(int i=src;i<=decc;++i) lev[i]=decc;
    q.push(decc);
    lev[decc]=0;
    int now,t;
    while(!q.empty())
    {
        now=q.front();
        q.pop();
        for(int i=front[now];i;i=nxt[i])
        {
            t=to[i];
            if(lev[t]==decc && val[i^1]) 
            {
                lev[t]=lev[now]+1;
                q.push(t);
            }
        }
    }
    return lev[src]!=decc;
}
 
int augment()
{
    int now=decc,flow=inf;
    int i;
    while(now!=src)
    {
        i=path[now];
        flow=min(flow,val[i]);
        now=from[i];
    }
    now=decc;
    while(now!=src)
    {
        i=path[now];
        val[i]-=flow;
        val[i^1]+=flow;
        now=from[i];
    }
    return flow;
}
 
int isap()
{
    int flow=0;
    if(!bfs()) return 0;
    memset(num,0,sizeof(num));
    for(int i=src;i<=decc;++i) num[lev[i]]++,cur[i]=front[i];
    int now=src,t;
    while(lev[src]<decc)
    {
        if(now==decc)
        {
            flow+=augment();
            now=src;
        }
        bool advanced=false;
        for(int i=cur[now];i;i=nxt[i])
        {
            t=to[i];
            if(lev[t]==lev[now]-1 && val[i])
            {
                advanced=true;
                path[t]=i;
                cur[now]=i;
                now=t;
                break;
            }
        }
        if(!advanced)
        {
            int mi=decc;
            for(int i=front[now];i;i=nxt[i])
                if(val[i]) mi=min(mi,lev[to[i]]);
            if(!--num[lev[now]]) break;
            num[lev[now]=mi+1]++;
            cur[now]=front[now];
            if(now!=src) now=from[path[now]];
        }
    }
    return flow;
}

int main()
{
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;++i)
    {
        scanf("%s",s+1);
        for(int j=1;j<=m;++j) 
        {
            mp[i][j]=s[j]-'0';
            if(mp[i][j]) id[i][j]=++cnt;
        }
    }
    src=1; decc=(cnt<<1|1)+1;
    int x,y;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
        {
            if(!mp[i][j]) continue;
            add(id[i][j]<<1,id[i][j]<<1|1,mp[i][j]);
            for(int r=1;r<=n;++r)
                for(int c=1;c<=m;++c)
                {
                    if(!mp[r][c] || (r==i && c==j)) continue;
                    if((r-i)*(r-i)+(c-j)*(c-j)<=k*k) add(id[i][j]<<1|1,id[r][c]<<1,mp[i][j]);
                    //if(abs(r-i)+abs(c-j)<=k) add(id[i][j]<<1|1,id[r][c]<<1,inf);
                }
            if(i<=k || j<=k || n-i<k || m-j<k) add(id[i][j]<<1|1,decc,inf);
        }
    int sum=0;
    for(int i=1;i<=n;++i)
    {
        scanf("%s",s+1);
        for(int j=1;j<=m;++j)
        {
            if(s[j]=='L') 
            {
                sum++;
                add(src,id[i][j]<<1,1);
            }
        }
    }
    cout<<sum-isap();
}

1066: [SCOI2007]蜥蜴

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 4407  Solved: 2245
[Submit][Status][Discuss]

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<=4

posted @ 2017-12-14 19:49  TRTTG  阅读(116)  评论(0编辑  收藏