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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章