拯救公主2
题目描述
公主被妖怪抓到了一个山洞里,为了尽快营救公主,王子决定不回城搬救兵去独自营救。山洞为矩形且十分空旷,其中生活着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列)
之后有k行每行两个数xi,yi(表示妖怪在xi行,yi列)
输出
离妖怪最近的距离
样例输入
3 3 2
1 3
3 1
样例输出
1
提示
k值变大
最近距离的算法为行数差加列数差(即从入口到公主的最短距离为(n-1)+(m-1))。
该题中:妖怪数目变大
程序的优化是:在计算最近距离时,先计算每行的离妖怪距离最近的值,更新过地图数组 Map 后,再每列用 DP 思想,一次从上到下地更新地图的值,再一次从下向上更新,继而取得每个点上距离每个妖怪的最近距离
源程序为:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
#define MIN(x,y) (x<y?x:y)
#define INF 0x3f3f3f3f
const int c[4][2]={{1,0},{-1,0},{0,-1},{0,1}};
int Map[1003][1003],vis[1003][1003],vis2[1003][1003];
int n,m,k,ax[1003][1003],by[1003][1003];
struct node{
int x,y;
int v;
friend bool operator < (const node &aa,const node &bb){
return aa.v<bb.v;
}
};
bool check(int i,int j){
if(i>=1 && i<=n && j>=1 && j<=m && Map[i][j]) return true;
else return false;
}
int bfs(int xx,int yy)
{
int dd=0;
priority_queue<node> q,p;
node now,tmp,now2,tmp2;
now.x=xx; now.y=yy; now.v=Map[xx][yy];
now2.x=n; now2.y=m; now2.v=Map[n][m];
q.push(now); p.push(now2);
vis[now.x][now.y]=1;
vis2[now2.x][now2.y]=1;
while(!q.empty() && !p.empty()){
now=q.top(); q.pop();
now2=p.top(); p.pop();
if(vis2[now.x][now.y]){
dd=1;
break;
}
if(vis[now2.x][now2.y]){
dd=2;
break;
}
for(int i=0;i<4;i++){
tmp.x=now.x+c[i][0];
tmp.y=now.y+c[i][1];
tmp.v=min(Map[tmp.x][tmp.y],now.v);
if(check(tmp.x,tmp.y) && !vis[tmp.x][tmp.y]){
q.push(tmp);
vis[tmp.x][tmp.y]=1;
}
tmp2.x=now2.x+c[i][0];
tmp2.y=now2.y+c[i][1];
tmp2.v=min(Map[tmp2.x][tmp2.y],now2.v);
if(check(tmp2.x,tmp2.y) && !vis2[tmp2.x][tmp2.y]){
p.push(tmp2);
vis2[tmp2.x][tmp2.y]=1;
}
}
}
if(dd==1){
int w=MIN(now.v,now2.v);
return w;
}
else if(dd==2){
int s=MIN(now.v,now2.v);
return s;
}
else return 0;
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&k)){
memset(Map,INF,sizeof(Map));
memset(vis,0,sizeof(vis));
memset(vis2,0,sizeof(vis2));
memset(ax,INF,sizeof(ax));
memset(by,INF,sizeof(by));
int a,b;
for(int i=1;i<=k;i++){
scanf("%d%d",&a,&b);
Map[a][b]=0;
for(int j=1;j<=m;j++)
Map[a][j]=MIN(Map[a][j],abs(b-j));
}
for(int i=1;i<=m;i++){
ax[1][i]=Map[1][i];
for(int j=2;j<=n;j++){
if(ax[j-1][i]+1<Map[j][i])
ax[j][i]=ax[j-1][i]+1;
else ax[j][i]=Map[j][i];
}
by[n][i]=Map[n][i];
for(int d=n-1;d>=1;d--){
if(by[d+1][i]+1<Map[d][i])
by[d][i]=by[d+1][i]+1;
else by[d][i]=Map[d][i];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
Map[i][j]=MIN(ax[i][j],by[i][j]);
}
}
printf("%d\n",bfs(1,1));
}
return 0;
}
运行时间:580ms
测试数据:
1000 1000 10
732 474
449 988
119 239
306 233
258 268
627 992
225 792
237 601
72 361
1 951
运行结果为:232
732 474
449 988
119 239
306 233
258 268
627 992
225 792
237 601
72 361
1 951