zoukankan      html  css  js  c++  java
  • [BZOJ 1066][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<=3

    Source

    此题出得不错,是一道经典的网络流题,由题意得,图中每一个结点(即石柱)都有容量,依据《训练指南》的提示,能够将每一个结点拆成两个点(暂且称入点和出点),两个点间的弧上容量等于原来的结点容量(即石柱高度,石柱上能经过的蜥蜴数等于石柱高度,每有一个蜥蜴经过此石柱,石柱高度-1,石柱相应的弧残量-1,后面能经过该石柱的蜥蜴数-1),再建立一个起点s和终点t,每一个有蜥蜴的石柱相应的入点就和起点s连接,s与入点间的弧容量为1(含义是该石柱仅仅能有一个蜥蜴,假设容量大于1,就有可能在跑最大流时出现一个石柱有多个蜥蜴的情况),每一个与边界距离足够近的石柱相应的出点和终点t连接,t与出点间的弧容量为+∞,这样t与出点间的弧容量不会影响到结果,此题的图就建立完毕了,再跑一遍最大流,最大流等于能逃脱的蜥蜴数量,输出时用总蜥蜴数减去能逃脱的蜥蜴数就可以

    我的思路是參考http://blog.csdn.net/jiangshibiao/article/details/20074193的做法,以下是他的题解中的图

    #include <stdio.h>
    #include <string.h>
    #include <queue>
    #define MAXN 1050
    #define MAXQ 20050
    #define INF 999999
    using namespace std;
    int r,c,d,cnt=0,acnt=0,ans=0; //cnt=网络中的点的个数(个数=石柱个数*2,一个石柱相应2个点),acnt=蜥蜴个数,ans=能够离开边界的蜥蜴个数
    int col[21][21]; //map数组保存网络,map[i][i+1]=第i个石柱的高度(点i->点i+1的容量),col[i][j]表示(i,j)的石柱编号
    char in[21][21],ani[21][21]; //in[i][j]保存(i,j)有无石柱,ani[i][j]保存(i,j)有无蜥蜴
    int map[MAXN][MAXN];
    int pre[MAXQ],q[MAXQ]; //pre[i]=点i的前一个点
    int min(int a,int b)
    {
    	if(a<b) return a;
    	return b;
    }
    void makePic(int x,int y) //在(x,y)与能从(x,y)跳到的边之间建一条无穷大边
    {
    	int i,j,k;
    	int now=col[x][y]+1; //now=该石柱相应的出点编号
    	for(i=1;i<=r;i++)
    		for(j=1;j<=c;j++)
    		{
    			if((i!=x||j!=y)&&(in[i][j]>'0')) //(i,j)是另外一个点,且(i,j)是石柱
    				if(d*d>=(x-i)*(x-i)+(y-j)*(y-j)) //(i,j)和(x,y)间距离小于最大跳跃距离
    					map[now][col[i][j]]=INF; //在(i,j)的出点和(x,y)的入点间建立一条无穷大边
    		}
    }
    void goOut() //将图中全部能跳出去的蜥蜴跳出,更新图
    {
    	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) //(i,j)与边界的最短距离小于跳跃距离
    			{
    				int now=col[i][j]+1; //now=该石柱相应的出点编号
    				map[now][cnt]=INF; //从该石柱相应出点到汇点间建一条无穷大的边,表明可从该石柱跳到边界外
    			}
    }
    void bfs_maxFlow() //bfs求最大流,数组模拟队列
    {
    	while(1)
    	{
    		int i,j,head=0,tail=1;
    		q[1]=0;
    		memset(pre,-1,sizeof(pre));
    		while(head<tail)
    		{
    			int now=q[++head]; //now=队首,队首出队
    			for(i=1;i<=cnt;i++)
    				if(pre[i]<0&&map[now][i]>0) //该点没有扩展过,且i和当前点now联通
    				{
    					q[++tail]=i; //与now连接的下一个结点入队
    					pre[i]=now;
    				}
    			if(pre[cnt]>0) break;
    		}
    		if(pre[cnt]<0) break; //找不到增广路,退出
    		int minFlow=INF; //最小残留流量
    		for(i=cnt;i!=0;i=pre[i])
    			minFlow=min(minFlow,map[pre[i]][i]); //更新最小残留容量
    		for(i=cnt;i!=0;i=pre[i])
    		{
    			//更新流量、残留容量
    			map[pre[i]][i]-=minFlow;
    			map[i][pre[i]]+=minFlow;
    		}
    		ans+=minFlow;
    	}
    }
    void init() //输入数据
    {
    	int i,j,k;
    	scanf("%ld%ld%ld",&r,&c,&d);
    	for(i=1;i<=r;i++)
    	{
    		scanf("%s",in[i]+1);
    		for(j=1;j<=c;j++)
    		{
    			if(in[i][j]!='0') //该点有石柱
    			{
    				cnt++; //石柱个数+1
    				col[i][j]=cnt;
    				map[cnt][cnt+1]=in[i][j]-48;
    				cnt++;
    			}
    		}
    	}
    	for(i=1;i<=r;i++)
    	{
    		scanf("%s",ani[i]+1);
    		for(j=1;j<=c;j++)
    		{
    			if(ani[i][j]=='L') //(i,j)有蜥蜴
    			{
    				acnt++;
    				map[0][col[i][j]]=1;
    			}
    			if(in[i][j]>'0')
    				makePic(i,j); //建图
    		}
    	}
    }
    int main()
    {
    	init(); //输入数据
    	cnt++;
    	goOut();
    	bfs_maxFlow();
    	printf("%ld",acnt-ans);
    	return 0;
    }


     

  • 相关阅读:
    iframe应用 相互之间发送消息 postMessage
    function angular.bootstrap()
    总结
    1-angular.bind
    jQuery treeTable v 1.4.2
    声明了一个模块和一个控制器AngularJS的处理过程
    angularJs $templateCache
    $.fn.zTree 的使用
    Java异常throws与throw的区别
    Pom报错
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/3978924.html
Copyright © 2011-2022 走看看