HDU 1983 - Kaitou Kid - The Phantom Thief (2)

22 篇文章 0 订阅

 

题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=1983

 

去年做时没做出来,木有思路。

 

今年再次碰到这题,初看还是木有思路。仔细一想,先暴力一发。。。  果然过了。。。

 

=======================================================================================================

 

因为 地图只有 8*8 ,并且最多只需要堵 4个地方 (起点或者终点的 四个方向)。。。

 

所以暴力枚举 前3个点的堵法,都不能堵的话,就输出4。

 

时间 O((8*8) * (8*8) * (8*8) * (8*8) ),约1600MS 。。。

 

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

struct Node{
	int x,y,has;
	Node(){}
	Node(int a,int b,int c){x=a,y=b,has=c;}
}que[200];

int fx[]={1,-1,0,0};
int fy[]={0,0,1,-1};

int res,n,m,T;
char map[10][10];
int si,sj;
int vis[8][8][2];

int bfs(){
	int s,t,k,nx,ny,has;
	memset(vis,-1,sizeof(vis));
	que[s=t=0]=Node(si,sj,0);
	vis[si][sj][0]=0;
	while(s<=t){
		Node no=que[s++];
		if(map[no.x][no.y]=='E' && no.has) return 0;
		if(vis[no.x][no.y][no.has]>=T) continue;
		for(k=0;k<4;k++){
			nx=no.x+fx[k];
			ny=no.y+fy[k];
			has=no.has;
			if(nx<0 || nx>=n || ny<0 || ny>=m) continue;
			if(map[nx][ny]=='#') continue;
			if(map[nx][ny]=='J') has=1;
			if(vis[nx][ny][has]!=-1) continue;
			vis[nx][ny][has]=vis[no.x][no.y][no.has]+1;
			que[++t]=Node(nx,ny,has);
		}
	}
	return 1;
}

int dfs(int v){
	if(v==0) return bfs();
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			if(map[i][j]=='.' || map[i][j]=='J'){
				char tmp=map[i][j];
				map[i][j]='#';
				if(dfs(v-1)) return 1;
				map[i][j]=tmp;
			}
	return 0;
}

int main(){
	int t,i,j;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d%d",&n,&m,&T);
		for(i=0;i<n;i++){
			scanf("%s",map[i]);
			for(j=0;j<m;j++)
				if(map[i][j]=='S')
					si=i,sj=j;
		}
		if(bfs()) puts("0");
		else if(dfs(1)) puts("1");
		else if(dfs(2)) puts("2");
		else if(dfs(3)) puts("3");
		else puts("4");
	}
	return 0;
}


=======================================================================================

后来想了一下,只需要先找到一条合理路径(取到金子,并且能够在T时刻前达到终点)。。。

 

那么我们枚举的范围,就可以缩减为这条路径上的所有点。。。(31 MS)

 

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

struct Node{
	int x,y,has,p;
	int rx[64],ry[64];
	Node(){}
	Node(int a,int b,int c,int v,int xx,int yy){x=a,y=b,has=c,p=v,rx[v]=xx,ry[v]=yy;}
}que[1000];

int fx[]={1,-1,0,0};
int fy[]={0,0,1,-1};

int res,n,m,T;
char map[10][10];
int si,sj,ei,ej;
bool vis[8][8][2];

void dfs(int num){
	if(num>=res) return ;
	int s,t,k;
	Node ne,no;
	memset(vis,false,sizeof(vis));
	que[s=t=0]=Node(si,sj,0,0,si,sj);
	vis[si][sj][0]=true;
	while(s<=t){
		no=que[s++];
		if(map[no.x][no.y]=='E' && no.has) break;
		if(no.p>=T) continue;
		for(k=0;k<4;k++){
			ne=no;
			ne.x+=fx[k],ne.y+=fy[k],ne.p++;
			if(ne.x<0 || ne.x>=n || ne.y<0 || ne.y>=m) continue;
			if(map[ne.x][ne.y]=='#') continue;
			if(map[ne.x][ne.y]=='J') ne.has=1;
			if(vis[ne.x][ne.y][ne.has]) continue;
			vis[ne.x][ne.y][ne.has]=true;
			ne.rx[ne.p]=ne.x;
			ne.ry[ne.p]=ne.y;
			que[++t]=ne;
		}
	}
	if(vis[ei][ej][1]){
		for(k=1;k<no.p;k++)
			if(map[no.rx[k]][no.ry[k]]=='.' || map[no.rx[k]][no.ry[k]]=='J'){ 
				char tmp=map[no.rx[k]][no.ry[k]];
				map[no.rx[k]][no.ry[k]]='#';
				dfs(num+1);
				map[no.rx[k]][no.ry[k]]=tmp;
			}
	}
	else res=num;
}

int main(){
	int t,i,j;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d%d",&n,&m,&T);
		for(i=0;i<n;i++){
			scanf("%s",map[i]);
			for(j=0;j<m;j++)
				if(map[i][j]=='S')
					si=i,sj=j;
				else if(map[i][j]=='E')
					ei=i,ej=j;
		}
		res=4;
		dfs(0);
		printf("%d\n",res); 
	}
	return 0;
}

/*

5
5 5 10000
S#JJJ
.#JJJ
..JJJ
..###
E....


5 5 1000
S#JJJ
.#JJJ
.#JJJ
.####
EJ...


*/


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值