蜥蜴 【有图包懂】 (网络流) gzoi

广州的同学看这里:

http://www.gdgzoi.com/JudgeOnline/problem.php?cid=1045&pid=3

Description

      在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。

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

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

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

【样例】

Xyz.in

Xyz.out

5 8 2

00000000

02000000

00321100

02000000

00000000

........

........

..LLLL..

........

........

1

【限制】

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

题目数据很小,所以做起来会很轻松(EK就行了)

接下来就是思路:一看就知道是网络流的题目。

1.首先是蜥蜴,与超源点连接,容量为一。

2.其次是石柱,每次有蜥蜴经过时高度减一,拆分成两点容量为石柱高度。

3.石柱与可以连接的石柱相连,容量为INF。

4.可以直接跳出的石柱与汇点相连,容量INF,石柱高度都行。

 

如果还不明白的看下面图:

石柱拆分我就没画了,看上面自己脑补一下,就像你们看番的时候就行

 

接下来就是贴代码了:

#include<iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define MAXN 1050
#define MAXQ 20050
#define INF 999999
using namespace std;
int r,c,d,cnt=0,acnt=0,ans=0;
int num[21][21];//用来记录每个有石柱的点的编号; 
int a[MAXQ];
int map[MAXN][MAXN],in[25][25];//map是矩阵图,记录点与点联系;in是石柱高度;
int p[MAXQ],q[MAXQ]; 
void makePic(int x,int y)//搜索有直接联系的边建图;
{int i,j;
int now=num[x][y]+1;
for(i=1;i<=r;i++)
for(j=1;j<=c;j++)
{
if((i!=x||j!=y) && (in[i][j]>0) && d*d>=(x-i)*(x-i)+(y-j)*(y-j)) 
map[now][num[i][j]]=INF;
}
}
 
void escape()//判断该石柱是否可以出逃;
{int i,j;
for(i=1;i<=r;i++)
for(j=1;j<=c;j++)
if(i-d<1||i+d>r||j-d<1||j+d>c) 
{
int now=num[i][j]+1; 
map[now][cnt]=INF; 
}
}
 
int Maxflow() //模板;
{int flow=0;
   for(;;)
    {   queue<int> Q;
      memset(p,-1,sizeof(p));       
        Q.push(0);
        while(!Q.empty())
        {int now=Q.front();Q.pop();
            for(int i=1;i<=cnt;i++)
                if(p[i]<0 && map[now][i]>0) 
                    {Q.push(i);
                     p[i]=now;
                     }
                  if(p[cnt]>0) break;
                }
        if(p[cnt]<0) break;
            int minFlow=INF; 
        for(int i=cnt;i!=0;i=p[i])
            minFlow=min(minFlow,map[p[i]][i]);
        for(int i=cnt;i!=0;i=p[i])
      {  map[p[i]][i]-=minFlow;
          map[i][p[i]]+=minFlow;
      }
        flow+=minFlow;
}
return flow;
}
 
void init()
{
    int i,j;
    char s;
    cin>>r>>c>>d;
    for(i=1;i<=r;i++)
        for(j=1;j<=c;j++)
    {cin>>s;
        in[i][j]=s-48;//石柱高度(该点是否有石柱);
        if(s!='0') 
            {num[i][j]=++cnt;
             map[cnt][cnt+1]=s-48;
            cnt++;}//石柱拆成俩点;
            }
 
 
    for(i=1;i<=r;i++)
        for(j=1;j<=c;j++)
        {cin>>s;
         if(s=='L') 
         {acnt++;
          map[0][num[i][j]]=1;//有蜥蜴的与源点连接;
           }
            if(in[i][j]>0)
                makePic(i,j);//每个石柱遍历建图(数据小);
             }
 
}
int main()
{
init(); 
cnt++;
escape();
cout<<acnt-Maxflow()<<endl;
return 0;
}

 

 

 

猜你喜欢

转载自blog.csdn.net/Wyt_code/article/details/81570666