HDU 4543

这道题感觉很坑。。不过,注意一些小问题。

参考http://www.cnblogs.com/Lattexiaoyu/archive/2013/03/31/2992553.html改进了原来自己的复杂度。

当无被占领时,其实枚举边缘也可以。但有计算公式,直接用了。

当有占领时,BFS出每个空的格到被占领的最小距离,然后枚举求出最小的D。

1)起先自己也是如上面的做,但做法不够优美T了。BFS时,起初是把占领的和未占的分开存枚举计算。其实这样复杂度就很高了。直接按一般的BFS就可以了,因为先到达空格的必定是距离短的,所以,复杂度变成了o(NM)。

2)枚举求D也有小技巧。直接三重循环必须T。可以改为枚举D,三重循环判断D是否符合要求,符合则D++,不符合即能得到答案了。

为什么不符合就能得到答案?因为排序后的点当枚举到q时,剩下的三重循环会把所有情况都列举到,所以不符合D-1就是解

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int n,m;

struct Node{
	int x,y,dis;
	Node(){}
	Node(int xx,int yy,int d){x=xx,y=yy,dis=d;}
}que[10300],dic[5300];
int cd,head,tail;
char s[100];
int dir[4][2]={
	{0,1},
	{0,-1},
	{1,0},
	{-1,0}
};


int cal(int i,int j,int x,int y){
	return abs(i-x)+abs(j-y);
}

int map[80][80];

int uslove(){/*
	int ans=1;
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			for(int k=0;k<m;k++){
				int t=min(cal(0,i,j,m-1),cal(j,m-1,n-1,k));
				ans=max(ans,min(cal(0,i,n-1,k),t));
			}
			for(int k=0;k<n;k++){
				int t=min(cal(0,i,j,m-1),cal(j,m-1,k,0));
				ans=max(ans,min(cal(0,i,k,0),t));
			}
		}
	}
//	printf("%d
",ans);*/
//	return ans;
	 if(n == 1) return m / 3;
	 if(m == 1) return n / 3; 
     return (2*n + 2*m - 4)/3;
}

bool cmp(Node a,Node b){
	if(a.dis<b.dis) return true;
	return false;
}

bool check(int x,int y){
	if(x>=0&&x<n&&y>=0&&y<m&&map[x][y]==0) return true;
	return false;
}

void BFS(){
/*	for(int i=0;i<cd;i++){
		dic[i].dis=200;
		for(int j=0;j<co;j++){
			dic[i].dis=min(dic[i].dis,cal(dic[i].x,dic[i].y,occ[j].x,occ[j].y));
	//		cout<<dis[i]<<endl;
		}
	}*/
	Node p,tmp;
	while(head<tail){
		p=que[head++];
		for(int i=0;i<4;i++){
			tmp.x=p.x+dir[i][0];
			tmp.y=p.y+dir[i][1];
			if(check(tmp.x,tmp.y)){
				tmp.dis=p.dis+1;
				map[tmp.x][tmp.y]=tmp.dis;
				dic[cd++]=Node(tmp.x,tmp.y,p.dis);
				que[tail++]=tmp;
			}
		}
	}
}

void slove(){
	/*
	int ans=-1;
	int t;
	for(int i=0;i<cd;i++){
		if(dis[i]<ans) continue;
		for(int j=i+1;j<cd;j++){
			t=min(dis[j],dis[i]);
			if(t<ans) continue;
			for(int k=j+1;k<cd;k++){
				int t1=min(dis[k],t);
				if(t1<ans) continue;
				t1=min(t1,cal(dic[i].x,dic[i].y,dic[j].x,dic[j].y));
				t1=min(t1,cal(dic[i].x,dic[i].y,dic[k].x,dic[k].y));
				t1=min(t1,cal(dic[j].x,dic[j].y,dic[k].x,dic[k].y));
				ans=max(t1,ans);
			}
		}
	}
	printf("%d
",ans);*/
	sort(dic,dic+cd,cmp);
	int q=0,d=1;
	while(q<cd){
		bool flag=false;
		for(int i=q;i<cd;i++){
			for(int j=i+1;j<cd;j++){
				if(cal(dic[i].x,dic[i].y,dic[j].x,dic[j].y)<d) continue;
				for(int k=j+1;k<cd;k++){
					if(cal(dic[i].x,dic[i].y,dic[k].x,dic[k].y)>=d&&cal(dic[k].x,dic[k].y,dic[j].x,dic[j].y)>=d){
						flag=true;
						break;
					}
				}
				if(flag) break;
			}
			if(flag) break;
		}
		if(!flag) break;
		d++;
		while(q<cd&&dic[q].dis<d)
		q++;
	}
	printf("%d
",d-1);
}

int main(){
	int T,icase=0;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&m);
		cd=0; int cc=0;
		head=tail=0;
		memset(map,0,sizeof(map));
		for(int i=0;i<n;i++){
			scanf("%s",s);
			for(int j=0;j<m;j++){
				if(s[j]=='F'){
					map[i][j]=1;
					que[tail++]=Node(i,j,1);
				}
				else cc++;
			}
		}
		printf("Case %d: ",++icase);
		if(cd==n*m){
			printf("%d
",uslove());
		}
		else{
			BFS();
			slove();
		}
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/jie-dcai/p/4421590.html