您的位置:首页 > 理论基础 > 数据结构算法

拯救公主

2015-11-15 17:46 501 查看
时间限制: 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
[j]=map
[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,t
4000
p3;
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;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息