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

思路:

经典的网络流题目,思考柱子高度的模型,我们可以将高度等价为,有该高度只蜥蜴可在这个柱子上跳,这样问题就变得明了啦对于每个石柱,我们把它拆成2个点,称为入点和出点,入点和出点连一条边,容量为高度,如果A石柱能跳到B石柱,就把出点A和入点B连一条边,容量为无限,这条边模拟的是跳的过程。如果该石柱能跳出去,就在该石柱出点和汇点T连一条边,容量无限。这条边模拟跳出去的过程。 如果该石柱有蜥蜴,在源点S和该石柱入点连一条边,容量为1.
这样的话,每个有蜥蜴的石柱上都有一只蜥蜴,如果该蜥蜴想从该石柱跳开,必定要先从该石柱入点跑到该石柱出点,这样会消耗1的容量,然后跳出去后,跳到另一石柱时,想再跳的话,又会消耗那个石柱的容量 ,直到跳到汇点T,贡献了1的流量。所以这幅图的最大流表示的就是能逃脱的蜥蜴数量,输出答案时减一下就行了。

代码:

#include<stdio.h>
#include<cstring>
#include<iostream>
const int INF=999999;
char c,u,a[21][21];
int map[1002][1002],fin[21][21],n,m,d,cnt,ant,ans,i,j,x[20001],pre[1001];
using namespace std;
void make_picture(int x,int y)
{
  int now=fin[x][y]+1;
  for (int i=1;i<=n;i++)
    for (int j=1;j<=m;j++)
      if ((i!=x||j!=y)&&(a[i][j]>'0'))
      {
        if (d*d>=(x-i)*(x-i)+(y-j)*(y-j))
          map[now][fin[i][j]]=INF;
      }
}
void go_down()
{
  for (int i=1;i<=n;i++)
    for (int j=1;j<=m;j++)
      if (i-d<1||i+d>n||j-d<1||j+d>m)
      {
        int now=fin[i][j]+1;
        map[now][cnt]=INF;
      }
}
void flow()
{
  while (true)
  {
    int h=0,t=1;x[1]=0;
    memset(pre,-1,sizeof(pre));
    while (h<t)
    {
      int now=x[++h];
      for (int i=1;i<=cnt;i++)
        if (pre[i]<0&&map[now][i]>0)
        {
          x[++t]=i;pre[i]=now;
        }
      if (pre[cnt]>0) break;
    }
    if (pre[cnt]<0) break;int small=INF;
    for (i=cnt;i!=0;i=pre[i]) small=min(map[pre[i]][i],small);
    for (i=cnt;i!=0;i=pre[i]) {map[pre[i]][i]-=small;map[i][pre[i]]+=small;}
    ans+=small;
  }
}
int main()
{
  scanf("%ld%ld%ld",&n,&m,&d);
  scanf("%c",&u);cnt=0;
  for (i=1;i<=n;i++)
  {
    for (j=1;j<=m;j++)
    {
      scanf("%c",&a[i][j]);
      if (a[i][j]!='0')
      {
        cnt++;fin[i][j]=cnt;
        map[cnt][cnt+1]=a[i][j]-48;cnt++;
      }
    }
    scanf("%c",&u);
  }
  for (i=1;i<=n;i++)
  {
    for (j=1;j<=m;j++)
    {
      scanf("%c",&c);
      if (c=='L') {ant++;map[0][fin[i][j]]=1;}
      if (a[i][j]>'0') {make_picture(i,j);}
    }
    scanf("%c",&u);
  }
  cnt++;go_down();
  flow();
  printf("%d",ant-ans);
  return 0;
}


发布了105 篇原创文章 · 获赞 10 · 访问量 3万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章