bfs:01迷宫(洛谷P1141)
作者:互联网
解析
乍一看:bfs板子题
冰法师最棒了
然鹅
看了一眼数据范围
心中已有画面
《面 堂 发 黑》
怎么办嘞?
我们想到:
因为该题来与去的可逆性
我们搜一次后,这些点以后都不会再用到
而且每次覆盖到的所有点答案都是一样的
由于第一个结论,我们不必再费心保留原图
由于第二个结论,我们可以用DP来解决
但熟悉bfs模板的小朋友都知道:
bfs模板中途是无法记录都曾有哪些元素曾进队的
(顺道送个bfs模板):
oid bfs(int x,int y){
queue<int>xq;
queue<int>yq;
xq.push(x);yq.push(y);
while(!xq.empty()){
int X,Y;
X=xq.front();
Y=yq.front();
int nx,ny;
for(int i=0;i<=3;i++){
nx=X+dx[i];
ny=Y+dy[i];
if(nx<=m&&nx&&ny<=n&&ny&&a[nx][ny]){
a[nx][ny]=0;
xq.push(nx);
yq.push(ny);
}
}
xq.pop();
yq.pop();
}
return;
}
解决方法1:
做一个数组存所有进过队的元素,或者直接用指针手写队列
但为了显出我们的高级 更好的代码效率
可以使用
解决方法2:
把坐标的两个数存进一个hash数k中
用same[i][j]=k表示(i,j)的答案与k所对应的答案相等
这样dp只需存入起点答案,其他点用same映射即可
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<deque>
#include<set>
#include<string>
using namespace std;
int a[1005][1005];
long long same[1005][1005];
long long dp[1005][1005];
int jd[1005][1005];
int m,n;
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
long long hash(int a,int b){
return a*1331+b;
}
long long bfs(int x,int y){
if(same[x][y]){
long long b=same[x][y] % 1331;
long long a=same[x][y] / 1331;
return dp[a][b];
}
if(dp[x][y]) return dp[x][y];
queue<int>xq;
queue<int>yq;
xq.push(x);yq.push(y);
jd[x][y]=0;
int tot=1;
while(!xq.empty()){
int X,Y;
X=xq.front();
Y=yq.front();
int nx,ny;
for(int i=0;i<=3;i++){
nx=X+dx[i];
ny=Y+dy[i];
if(nx<=m&&nx&&ny<=m&&ny&&a[nx][ny]+a[X][Y]==1&&jd[nx][ny]){
jd[nx][ny]=0;
same[nx][ny]=hash(x,y);
tot++;
xq.push(nx);
yq.push(ny);
}
}
//a[X][Y]=-10;
xq.pop();
yq.pop();
}
return dp[x][y]=tot;
}
int main(){
int t,r;
scanf("%d%d",&m,&n);
for(int i=1;i<=m;i++){
for(int j=1;j<=m;j++){
scanf("%1d",&a[i][j]);
dp[i][j]=same[i][j]=0;
jd[i][j]=1;
}
}
for(int i=1;i<=n;i++){
scanf("%d%d",&t,&r);
printf("%lld\n",bfs(t,r));
}
return 0;
}
AC快乐!!!
(点赞评论了解一下qwq)
标签:nx,xq,洛谷,int,long,bfs,ny,P1141,include 来源: https://blog.csdn.net/BUG_Creater_jie/article/details/113408140