拯救公主

27 篇文章 0 订阅
19 篇文章 0 订阅
时间限制: 1 Sec   内存限制: 128 MB
[ 提交][ 状态][ 讨论版]

题目描述

公主被妖怪抓到了一个山洞里,为了尽快营救公主,王子决定不回城搬救兵去独自营救。山洞为矩形且十分空旷,其中生活着K个妖怪。幸运的是这些妖怪晚上都会睡觉并且没人守夜。但是若是离妖怪太近就会惊醒它,其他的妖怪也会被惊醒,所以我们要找一条距离所有妖怪都很远的路。我们把山洞分为了n*m个格子,走到相邻的格子(不含对角)王子需要一步,妖怪只占一个格子的大小。王子希望你给他一条尽可能安全的路,你只需要告诉他,这条路上离妖怪最近的时候距离是多少(最少走K步可到则认为最近距离为k)。入口在1行1列,公主在n行m列。

输入

n,m,k(地图为n行*m列,k为妖怪个数)(1<n,m<=1000,1<k<=n*m)
之后有k行每行两个数xi,yi(表示妖怪在xi行,yi列)

输出

离妖怪最近的距离

样例输入

3 3 21 33 1

样例输出

1

提示


k值变大



最近距离的算法为行数差加列数差(即从入口到公主的最短距离为(n-1)+(m-1)


//双向优先队列+dp 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
const int INF=9999999;
struct node{
	int x,y,s;
	bool operator < (const node &a) const{
	  return a.s>s;
	} 
};
int n,m,k,mm,mmm,flag,sum,pd1[1110][1110],pd2[1110][1110],z[1110][1110],dp[1110][1110];
int e[1110][1110],b[1110],s[1110],map3[1110][1110],map[1110][1110],map1[1110][1110],map2[1110][1110];
int c[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int min(int a,int b){
	return a<b?a:b;
} 
int insert(int b,int c){
	if(b<1 || b>n || c<1 || c>m || e[b][c]) return false;
	return true;
}
int bfs(int x1,int y1){
	struct node t1,t2,t3,tp1,tp2,tp3;
	priority_queue<node> q1,q2;
	t1.x=x1;t1.y=y1;t1.s=map3[t1.x][t1.y];
	q1.push(t1);
	pd1[t1.x][t1.y]=1;
	tp1.x=n;tp1.y=m;tp1.s=map3[tp1.x][tp1.y];
	q2.push(tp1);
	pd2[tp1.x][tp1.y]=2;
	while(!q1.empty() && !q2.empty()){
		t2=q1.top();q1.pop();
		tp2=q2.top();q2.pop();
		if(pd1[tp2.x][tp2.y]){
			flag=1;
			int u=min(t2.s,tp2.s);
			return u;
		}
		if(pd2[t2.x][t2.y]){
			flag=1;
			int uu=min(t2.s,tp2.s);
			return uu;
		}
	    for(int i=0;i<4;i++){
	    	t3.x=t2.x+c[i][0];
	    	t3.y=t2.y+c[i][1];
	    	int q=min(map3[t3.x][t3.y],t2.s);
	    	t3.s=q;
	    	if(insert(t3.x,t3.y) && !pd1[t3.x][t3.y]){
	    		q1.push(t3);
	    		pd1[t3.x][t3.y]=1;
	    	}
	    	
	    	
	    	tp3.x=tp2.x+c[i][0];
	    	tp3.y=tp2.y+c[i][1];
	    	int qq=min(map3[tp3.x][tp3.y],tp2.s);
	    	tp3.s=qq;
	    	if(insert(tp3.x,tp3.y) && !pd2[tp3.x][tp3.y]){
	    		q2.push(tp3);
	    		pd2[tp3.x][tp3.y]=1;
	    	}
	    }
	}
	return 0;
}
int main(){
           	int x,y,mid;
	while(scanf("%d%d%d",&n,&m,&k)!=EOF){
	    flag=0;mid=0;
		memset(e,0,sizeof(e));
		memset(z,0,sizeof(z));
		memset(b,0,sizeof(b));
		memset(s,0,sizeof(s));
		memset(pd1,0,sizeof(pd1));
		memset(pd2,0,sizeof(pd2));
		memset(map,INF,sizeof(map));
		memset(map1,INF,sizeof(map1));
		memset(map2,INF,sizeof(map2));
		memset(map3,0,sizeof(map3));
		for(int i=0;i<k;i++){
		   scanf("%d%d",&x,&y);
		   e[x][y]=1;
		   b[i]=x;
		   s[i]=y;
		   map[x][y]=0;
		   for(int j=1;j<=m;j++){
		   	map[x][j]=min(abs(y-j),map[x][j]);
		   }
		}
		
		for(int j=1;j<=m;j++){
			map1[1][j]=map[1][j];
			for(int i=2;i<=n;i++){
				if(map[i][j]>map1[i-1][j]+1)
					map1[i][j]=map1[i-1][j]+1;
				else
				    map1[i][j]=map[i][j];
			}
			
			map2[n][j]=map[n][j];
		   	for(int i=n-1;i>=1;i--){
				if(map[i][j]>map2[i+1][j]+1)
				  map2[i][j]=map2[i+1][j]+1;
				else
				  map2[i][j]=map[i][j];
			}
		}
		 
		 for(int i=1;i<=n;i++){
		 	for(int j=1;j<=m;j++){
		 		map3[i][j]=min(map1[i][j],map2[i][j]);
		 	}
		 }
	 
		   int sum=bfs(1,1);
		   if(flag)
	       printf("%d\n",sum);
	       else
	       printf("0\n");
	}  
	return 0;
} 




//单向广度优先搜索 

#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;
struct node{
	int x,y,s;
	bool operator < (const node &a) const{
	  return a.s>s;
	} 
};
int n,m,k,mm;
int e[1110][1110],b[1110],s[1110],dp[1110][1110];
int c[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int cmp(int xx,int yy){
	if(dp[xx][yy]) return dp[xx][yy];
	int mixn=9999999;
	for(int i=0;i<k;i++){
		int ss=abs(xx-b[i])+abs(yy-s[i]);
		if(ss<mixn)
		 mixn=ss;
	}
	dp[xx][yy]=mixn;
	return mixn;
}
int bfs(int x1,int y1){
	struct node t1,t2,t3;
	priority_queue<node> q;
	int qq=cmp(x1,y1);
	t1.x=x1;t1.y=y1;t1.s=qq;
	q.push(t1);
	while(!q.empty()){
		t2=q.top();q.pop();
		if(mm>t2.s)
		   mm=t2.s;
		for(int i=0;i<4;i++){
			t3.x=t2.x+c[i][0];
			t3.y=t2.y+c[i][1];
			int kk=cmp(t3.x,t3.y);
			t3.s=kk;
			if(t3.x<1 || t3.x>n || t3.y<1 || t3.y>m || e[t3.x][t3.y]==1)
			continue;
			if(t3.x==n && t3.y==m){
				return mm;
			} 
			q.push(t3);
			e[t3.x][t3.y]=1;
	    }
	}
	return 0; 
}
int main(){
	 	int x,y;
	while(scanf("%d%d%d",&n,&m,&k)!=EOF){
		mm=9999999;
		memset(b,0,sizeof(b));
		memset(s,0,sizeof(s));
		memset(e,0,sizeof(e));
		memset(dp,0,sizeof(dp));
		   for(int i=0;i<k;i++){
		   	  scanf("%d%d",&x,&y);
		   	  e[x][y]=1;
		   	  b[i]=x;
		   	  s[i]=y;
		   }
		   int flag=bfs(1,1);
		   if(flag)
	       printf("%d\n",flag);
	       else
	       printf("0\n");
	}  
	return 0;
} 

//广度双向优先搜索

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
struct node{
	int x,y,s;
	bool operator < (const node &a) const{
	  return a.s>s;
	} 
};
int n,m,k,mm,mmm,flag,sum,pd1[1110][1110],pd2[1110][1110],z[1110][1110],dp[1110][1110];
int e[1110][1110],b[1110],s[1110];
int c[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int min(int a,int b){
	return a<b?a:b;
}
int cmp(int xx,int yy){
	if(dp[xx][yy]) return dp[xx][yy];
	int mixn=9999999;
	for(int i=0;i<k;i++){
		int ss=abs(xx-b[i])+abs(yy-s[i]);
		if(ss<mixn)
		mixn=ss;
	}
	dp[xx][yy]=mixn;
	return mixn;
}
int insert(int b,int c){
	if(b<1 || b>n || c<1 || c>m || e[b][c]) return false;
	return true;
}
int bfs(int x1,int y1){
	struct node t1,t2,t3,tp1,tp2,tp3;
	priority_queue<node> q1,q2;
	t1.x=x1;t1.y=y1;t1.s=cmp(x1,y1);
	q1.push(t1);
	pd1[t1.x][t1.y]=1;
	tp1.x=n;tp1.y=m;tp1.s=cmp(n,m);
	q2.push(tp1);
	pd2[tp1.x][tp1.y]=2;
	while(!q1.empty() && !q2.empty()){
		t2=q1.top();q1.pop();
		tp2=q2.top();q2.pop();
		if(pd1[tp2.x][tp2.y]){
			flag=1;
			int u=min(t2.s,tp2.s);
			return u;
		}
		if(pd2[t2.x][t2.y]){
			flag=1;
			int uu=min(t2.s,tp2.s);
			return uu;
		}
	    for(int i=0;i<4;i++){
	    	t3.x=t2.x+c[i][0];
	    	t3.y=t2.y+c[i][1];
	    	int q=min(cmp(t3.x,t3.y),t2.s);
	    	t3.s=q;
	    	if(insert(t3.x,t3.y) && !pd1[t3.x][t3.y]){
	    		q1.push(t3);
	    		pd1[t3.x][t3.y]=1;
	    	}
	    	
	    	
	    	tp3.x=tp2.x+c[i][0];
	    	tp3.y=tp2.y+c[i][1];
	    	int qq=min(cmp(tp3.x,tp3.y),tp2.s);
	    	tp3.s=qq;
	    	if(insert(tp3.x,tp3.y) && !pd2[tp3.x][tp3.y]){
	    		q2.push(tp3);
	    		pd2[tp3.x][tp3.y]=1;
	    	}
	    }
	}
	return 0;
}
int main(){
		int x,y;
	while(scanf("%d%d%d",&n,&m,&k)!=EOF){
		mm=9999999;mmm=9999999;flag=0;sum=0;
		memset(b,0,sizeof(b));
		memset(s,0,sizeof(s));
		memset(e,0,sizeof(e));
		memset(pd1,0,sizeof(pd1));
		memset(pd2,0,sizeof(pd2));
		memset(z,0,sizeof(z));
		memset(dp,0,sizeof(dp));
		   for(int i=0;i<k;i++){
		   	  scanf("%d%d",&x,&y);
		   	  e[x][y]=1;
		   	  b[i]=x;
		   	  s[i]=y;
		   }
		   int sum=bfs(1,1);
		   if(flag)
	       printf("%d\n",sum);
	       else
	       printf("0\n");
	}  
	return 0;
} 



//bfs+二分 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
struct node{
	int x,y,s;
};
int n,m,k,flag,sum,dp[1110][1110],vis[1110][1110],z[1110];
int e[1110][1110],b[1110],s[1110];
int c[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int cmp(int xx,int yy){
	if(dp[xx][yy]) return dp[xx][yy];
	int mixn=9999999;
	for(int i=0;i<k;i++){
		int ss=abs(xx-b[i])+abs(yy-s[i]);
		if(ss<mixn)
		mixn=ss;
	}
	dp[xx][yy]=mixn;
	return mixn;
}
int insert(int b,int c){
	if(b<1 || b>n || c<1 || c>m || e[b][c]) return false;
	return true;
}
int cmp1(int xx,int yy){
	int maxn=0;
	for(int i=0;i<k;i++){
		int ss=abs(xx-b[i])+abs(yy-s[i]);
		if(ss>maxn)
		maxn=ss;
	}
	return maxn;
}
int bfs(int r){
	memset(vis,0,sizeof(vis));
	struct node t1,t2,t3;
	queue<node> q;
	t1.x=1;t1.y=1;t1.s=cmp(t1.x,t1.y);
	vis[t1.x][t1.y]=1;
    q.push(t1);
	while(!q.empty()){
		t2=q.front();q.pop();
		for(int i=0;i<4;i++){
			t3.x=t2.x+c[i][0];
			t3.y=t2.y+c[i][1];
			int rr=cmp(t3.x,t3.y);
			if(insert(t3.x,t3.y) && vis[t3.x][t3.y]==0 && rr>=r){
				if(t3.x==n && t3.y==m){
			       return 1;
		        }
				q.push(t3);
				vis[t3.x][t3.y]=1;
			}
		}
	}	
	return 0;
}
int main(){
			int x,y,mid;
	while(scanf("%d%d%d",&n,&m,&k)!=EOF){
	    flag=0;mid=0;
		memset(b,0,sizeof(b));
		memset(s,0,sizeof(s));
		memset(e,0,sizeof(e));
		memset(dp,0,sizeof(dp));
		memset(z,0,sizeof(z));
		memset(vis,0,sizeof(vis));
		for(int i=0;i<k;i++){
		   scanf("%d%d",&x,&y);
		   e[x][y]=1;
		   b[i]=x;
		   s[i]=y;
		}
		int kk=cmp1(1,1),left=0;
	    while(left<=kk){
	    	mid=(left+kk)/2;
	    	if(bfs(mid)){
	    		flag=1;
	    		left=mid+1;
	    	}   
	    	else{
	    		flag=2;
	    		kk=mid-1;
	    	}
	    }
	    if(flag==1)
		cout << mid << endl;
		else if(flag==2){
		   if(mid==0) cout << "0" << endl;	
	       else cout << mid-1 << endl;
	    }
	}
	return 0;
} 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值