bzoj1066 蜥蜴

1066: [SCOI2007]蜥蜴

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 3916  Solved: 1965
[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

bzoj上的第三道題目,第一道非水題......

其實就是一道簡單的最大流問題,關鍵是建模,建完模之後直接複製模板就行了

把每兩個石柱之間看做是一個點,石柱的高度就是這兩個節點的容量
如圖,a和b之間容量爲3,b和c之間容量爲2

下面是代碼
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string.h>
#include <cmath>
#include <queue>
#define maxn 821396745
using namespace std;
int ans,tot,fin[1010][1010];
char high[1010][1010];
int n,m,s,t,f[11000],flow[11000],d,map[1000][1000];
queue <int> q;
void make(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)&&(high[i][j]>'0'))  
			{  
				if(d>=sqrt((x-i)*(x-i)+(y-j)*(y-j)))  
					map[now][fin[i][j]]=maxn;  
    		}
}
void go()
{
	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 de=fin[i][j]+1;  
				map[de][tot]=maxn;  
			}  
}
int bfs(int s,int t)
{
	while(!q.empty())
		q.pop();
	memset(f,-1,sizeof(f));
	f[s]=0;
	flow[s]=maxn;
	q.push(s);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		if(u==t)	break;
		for(int v=1;v<=tot;v++)
		{
			if(map[u][v]>0&&f[v]==-1)
			{
				f[v]=u;
				flow[v]=min(flow[u],map[u][v]);
				q.push(v);
			}
		}
	}
	if(f[t]==-1)
		return -1;
	else 
		return flow[t];
}
int maxflow(int s,int t)
{
	int maxf=0;
	d=0;
    while((d=bfs(s,t))!=-1)
    {
    	int aim=t;
    	while(aim!=s)
    	{
    		map[f[aim]][aim]-=d;
    		map[aim][f[aim]]+=d;
    		aim=f[aim];
    	}
    	maxf+=d;
    }
    return maxf;
}
int main()
{
	scanf("%d%d%d",&n,&m,&d);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			cin>>high[i][j];
			if(high[i][j]!='0')
			{
				fin[i][j]=++tot;
				map[tot][++tot]=high[i][j]-'0';
			}
		}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			char cp;
			cin>>cp;
			if(cp=='L')
			{
				ans++;
				map[0][fin[i][j]]=1;
			}
			if(high[i][j]>'0')
				make(i,j);
		}
	tot++;
	go();
    printf("%d",ans-maxflow(0,tot));
    return 0;
}


發佈了51 篇原創文章 · 獲贊 7 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章