HDU 4528

一直在纠结怎么样表示找到了人,,,开始时竟灰笨得设两个BOOL。后来参考别人的可以使用二进制位。

另外,此处有一个剪枝就是,就到达该点之后的状态的found(即找到人的状态)在之前已出现过,可以剪去。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;
bool flag[105][105][4];
char map[105][105];
int see[105][105];
int n,m,lim,sx,sy;

int dir[4][2]={
	{0,1},
	{0,-1},
	{1,0},
	{-1,0}
};

struct Status{
	int x,y;
	int found,cnt;
	Status(){
		found=0;
	}
};

void Init(){
	memset(see,0,sizeof(see));
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(map[i][j]=='S'){
				sx=i,sy=j;
			}
			if(map[i][j]=='X') continue;
			int ii=i,jj=j;
			while(jj>=1&&(map[ii][jj]=='.'||map[ii][jj]=='S')) jj--;
			if(jj>=1&&map[ii][jj]=='D') see[i][j]|=1;
			if(jj>=1&&map[ii][jj]=='E') see[i][j]|=2;
			ii=i,jj=j;
			while(jj<=m&&(map[ii][jj]=='.'||map[ii][jj]=='S')) jj++;
			if(jj<=m&&map[ii][jj]=='D') see[i][j]|=1;
			if(jj<=m&&map[ii][jj]=='E') see[i][j]|=2;
			ii=i,jj=j;
			while(ii<=n&&(map[ii][jj]=='.'||map[ii][jj]=='S')) ii++;
			if(ii<=n&&map[ii][jj]=='D') see[i][j]|=1;
			if(ii<=n&&map[ii][jj]=='E') see[i][j]|=2;
			ii=i,jj=j;
			while(ii>=1&&(map[ii][jj]=='.'||map[ii][jj]=='S')) ii--;
			if(ii>=1&&map[ii][jj]=='D') see[i][j]|=1;
			if(ii>=1&&map[ii][jj]=='E') see[i][j]|=2;
		}
	}
}

bool ok(int x,int y){
	if(x>=1&&x<=n&&y>=1&&y<=m) return true;
	return false;
}

bool slove(){
	memset(flag,false,sizeof(flag));
	Status s,t;
	s.x=sx,s.y=sy,s.found=see[s.x][s.y],s.cnt=0;
//	cout<<s.found<<endl;
	queue<Status>que;
	que.push(s);
	while(!que.empty()){
		s=que.front();
		que.pop();
		if(s.cnt>lim) return false;
		else if(s.found==3){ printf("%d\n",s.cnt); return true; }
		flag[s.x][s.y][s.found]=true;
		for(int i=0;i<4;i++){
			t=s;
			t.x=s.x+dir[i][0];
			t.y=s.y+dir[i][1];
			if(map[t.x][t.y]=='D'||map[t.x][t.y]=='E'||map[t.x][t.y]=='X'||!ok(t.x,t.y)) continue;
			t.found|=see[t.x][t.y];
			if(flag[t.x][t.y][t.found]) continue;
			flag[t.x][t.y][t.found]=true;
			t.cnt++;
			que.push(t);
		}
	}
	return false;
}

int main(){
	int T,t=0;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d%d",&n,&m,&lim);
		for(int i=1;i<=n;i++)
		scanf("%s",map[i]+1);
		Init();
		printf("Case %d:\n",++t);
		if(!slove()){
			puts("-1");
		}
	}
	return 0;
}

  

posted @ 2015-03-22 22:07  chenjunjie1994  阅读(274)  评论(0编辑  收藏  举报