三.搜索与图论(未完结)

DFS(深搜)

之前写过三篇关于dfs的

练习总结:

基础算法--递归搜索DFS练习总结(上)-CSDN博客

基础算法--递归搜索DFS练习总结(中)-CSDN博客

基础算法--递归搜索DFS练习总结(下)-CSDN博客

以下题目均为

补充练习: 

P1460 [USACO2.1] 健康的荷斯坦奶牛 Healthy Holsteins 

第一种暴力搜索dfs(超时未AC 90 points):

#include<iostream>
#include<cstring>
using namespace std;
int n,m,a[30],b[20][30],c[30],ans;
bool flag[20],key;
bool check(){for(int i=1;i<=n;i++){for(int j=1;j<=m;j++) if(flag[j]) c[i]+=b[j][i];if(a[i]>c[i]) return false;}return true;
}
void dfs(int x,int cnt){if(x==cnt+1){if(check()) {key=true;ans=cnt;}memset(c,0,sizeof c);return ;}for(int i=x;i<=m;i++){if(!flag[i]){flag[i]=true;dfs(x+1,cnt);if(key) return ;flag[i]=false;}}
}
int main(){cin>>n;for(int i=1;i<=n;i++) cin>>a[i];cin>>m;for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) cin>>b[i][j];for(int i=1;i<=m;i++){memset(flag,0,sizeof flag);memset(c,0,sizeof c);dfs(1,i);if(key){cout<<ans<<" ";for(int i=1;i<=m;i++) if(flag[i]) cout<<i<<" ";return 0;}}
}

第二种暴力搜索dfs(AC):

#include<iostream>
using namespace std;
int n,m,a[30],b[20][30],c[30],ans=1e9,res[30];
//数组c:每次搜索选的饲料编号,数组res:存储解
//判断每次选的那些饲料中的维生素之和是不是都大于等于牛需要的量 
bool check(int x){for(int i=1;i<=n;i++){int sum=0;for(int j=1;j<=x;j++) sum+=b[c[j]][i];if(sum<a[i]) return false;}return true;
}
void dfs(int curPos,int curCnt){if(curPos>m){//当前位置超过边界if(check(curCnt)){//必须使牛够吃if(curCnt<ans){//如果小于以前的最优解ans=curCnt;//更新答案for(int i=1;i<=m;i++) res[i]=c[i];//更新答案数组}}return ;}c[curCnt+1]=curPos;//把当前位置放在数组里dfs(curPos+1,curCnt+1);//搜索一步c[curCnt+1]=0;//回溯一步dfs(curPos+1,curCnt);//如果不选第curPos种饲料
}
int main(){cin>>n;for(int i=1;i<=n;i++) cin>>a[i];cin>>m;for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) cin>>b[i][j];dfs(1,0);cout<<ans<<" ";for(int i=1;i<=ans;i++) cout<<res[i]<<" ";return 0;
}

P1451 求细胞数量

dfs(AC):

思路:不为0的地方就是细胞,然后dfs搜连通块,把搜到的都归0,保证不重复

#include<iostream>
using namespace std;
int n,m,ans;
char a[105][105];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
void dfs(int x,int y){if(x<0||y<0||x>=n||y>=m) return ;a[x][y]='0';for(int i=0;i<4;i++){int xx=x+dx[i],yy=y+dy[i];if(xx>=0&&xx<n&&yy>=0&&yy<m){if(a[xx][yy]!='0'){dfs(xx,yy);}}}
}
int main(){cin>>n>>m;for(int i=0;i<n;i++) cin>>a[i];for(int i=0;i<n;i++) {for(int j=0;j<m;j++) {if(a[i][j]!='0'){dfs(i,j);ans++;}}}cout<<ans<<endl;return 0;
}

P1331 海战

dfs(AC):

和细胞一样的思路,唯一需要注意的是对于斜着连着的情况要特殊输出

#include<iostream>
using namespace std;
int n,m,ans;
char a[1005][1005];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
bool flag;
void dfs(int x,int y){if(flag) return ;if(x<0||y<0||x>=n||y>=m) return ;a[x][y]='.';if(a[x-1][y+1]=='#'&&a[x-1][y]=='.'&&a[x][y+1]=='.') {flag=true; return ;}if(a[x+1][y+1]=='#'&&a[x+1][y]=='.'&&a[x][y+1]=='.') {flag=true; return ;}if(a[x+1][y-1]=='#'&&a[x+1][y]=='.'&&a[x][y-1]=='.') {flag=true; return ;}if(a[x-1][y-1]=='#'&&a[x-1][y]=='.'&&a[x][y-1]=='.') {flag=true; return ;}for(int i=0;i<4;i++){int xx=x+dx[i],yy=y+dy[i];if(xx>=0&&xx<n&&yy>=0&&yy<m){if(a[xx][yy]!='.'){dfs(xx,yy);}}}
}
int main(){cin>>n>>m;for(int i=0;i<n;i++) cin>>a[i];for(int i=0;i<n;i++) {for(int j=0;j<m;j++) {if(a[i][j]!='.'){dfs(i,j);ans++;}}}if(!flag) cout<<"There are "<<ans<<" ships."<<endl;else cout<<"Bad placement."<<endl;return 0;
}

B3625 迷宫寻路

 dfs(AC):

#include<iostream>
using namespace std;
int n,m;
char a[105][105];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
void dfs(int x,int y){if(a[x-1][y]=='#'){if(a[x][y+1]=='#'){if(a[x+1][y]=='#'){if(a[x-1][y]=='#'){return ;}}}}for(int i=0;i<4;i++){int xx=x+dx[i],yy=y+dy[i];if(xx>0&&xx<=n&&yy>0&&yy<=m&&a[xx][yy]=='.'){a[xx][yy]='#';dfs(xx,yy);}}
}
int main(){cin>>n>>m;for(int i=0;i<=m+1;i++) a[0][i]='#',a[n+1][i]='#';for(int i=1;i<=n;i++) a[i][0]='#',a[i][m+1]='#';for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j];dfs(1,1);if(a[n][m]=='#') cout<<"Yes"<<endl;else cout<<"No"<<endl;return 0;
}

 bfs(AC):

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
typedef pair<int,int> pii;
int n,m,d[105][105];
char a[105][105];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
int bfs(){queue<pii>q;q.push({0,0});memset(d,-1,sizeof d);d[0][0]=0;while(q.size()){auto t=q.front();q.pop();for(int i=0;i<4;i++){int x=t.first+dx[i],y=t.second+dy[i];if(x>=0&&x<n&&y>=0&&y<m&&a[x][y]=='.'&&d[x][y]==-1){d[x][y]=d[t.first][t.second]+1;q.push({x,y});}}}return d[n-1][m-1];
}
int main(){cin>>n>>m;for(int i=0;i<n;i++) cin>>a[i];if(bfs()==-1) cout<<"No"<<endl;else cout<<"Yes"<<endl;return 0;
}

P1162 填涂颜色

思路:

利用dfs把原来的0变成1,并且标记数组记住原来的0,方便后续输出

然后图中剩下的1就是1,剩下的0就是2,输出即可

#include<iostream>
using namespace std;
const int N=35;
int n,a[N][N],flag[N][N];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
void dfs(int x,int y){a[x][y]=1;flag[x][y]=1;if(a[x-1][y]==1){if(a[x][y+1]==1){if(a[x+1][y]==1){if(a[x][y-1]==1){return ;}}}}for(int i=0;i<4;i++){int xx=x+dx[i],yy=y+dy[i];if(xx>0&&xx<=n&&yy>0&&yy<=n&&a[xx][yy]==0){dfs(xx,yy);}}
}
int main(){cin>>n;for(int i=0;i<=n+1;i++) a[0][i]=1,a[n+1][i]=1;for(int i=1;i<=n;i++) a[i][0]=-1,a[i][n+1]=-1;for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>a[i][j];for(int i=1;i<=n;i++){if(a[1][i]==0) {flag[1][i]=1;dfs(1,i);}if(a[n][i]==0) {flag[n][i]=1;dfs(n,i);}}for(int i=1;i<=n-1;i++){if(a[i][1]==0) {flag[i][1]=1;dfs(i,1);}if(a[i][n]==0) {flag[i][n]=1;dfs(i,n);}}for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(flag[i][j]) cout<<"0"<<" ";else{if(a[i][j]) cout<<"1"<<" ";else cout<<"2"<<" ";}}cout<<endl;}return 0;
}

P1506 拯救oibh总部

 和上面几题一样的思路dfs(AC):

#include<iostream>
using namespace std;
const int N=505;
int n,m,ans;
char a[N][N];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
void dfs(int x,int y){a[x][y]='*';if(a[x-1][y]=='*'&&x-1>=0&&x-1<n&&y>=0&&y<m-1){if(a[x][y+1]=='*'&&x>=0&&x<n&&y+1>=0&&y+1<m-1){if(a[x+1][y]=='*'&&x+1>=0&&x+1<n&&y>=0&&y<m-1){if(a[x][y-1]=='*'&&x>=0&&x<n&&y-1>=0&&y-1<m-1){return ;}}}}for(int i=0;i<4;i++){int xx=x+dx[i],yy=y+dy[i];if(a[xx][yy]=='0'&&xx>=0&&xx<n&&yy>=0&&yy<m){dfs(xx,yy);}}
}
int main(){cin>>n>>m;for(int i=0;i<n;i++) cin>>a[i];for(int i=0;i<m;i++){if(a[0][i]=='0') dfs(0,i);if(a[n-1][i]=='0') dfs(n-1,i);}for(int i=1;i<n-1;i++){if(a[i][0]=='0') dfs(i,0);if(a[i][m-1]=='0') dfs(i,m-1);}for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(a[i][j]=='0') ans++;cout<<ans<<endl;return 0;
}

P8662 [蓝桥杯 2018 省 AB] 全球变暖

这题非常重要的一点是:原来的岛屿经过海水淹没后(只要没完全被淹没),仍然认为他们是同一座岛屿!!!

模拟下图样例:

海平面上升后:

答案为:4(原来有8个岛屿,红色是没有被完全淹没的,那么被完全淹没的就有4个)

因此思路是:先dfs所有原来的岛屿,接着dfs没被完全淹没的岛屿,最后相减得结果(AC):

#include<iostream>
using namespace std;
const int N=1005;
char a[N][N],b[N][N];
int n,res,ans;
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
void dfs_all(int x,int y){b[x][y]='.';if(b[x-1][y]=='.'&&x-1>=0&&x-1<n&&y>=0&&y<n){if(b[x][y+1]=='.'&&x>=0&&x<n&&y+1>=0&&y+1<n){if(b[x+1][y]=='.'&&x+1>=0&&x+1<n&&y>=0&&y<n){if(b[x][y-1]=='.'&&x>=0&&x<n&&y-1>=0&&y-1<n){return ;}}}}for(int i=0;i<4;i++){int xx=x+dx[i],yy=y+dy[i];if(b[xx][yy]=='#'){dfs_all(xx,yy);}}
}
void dfs_rest(int x,int y){a[x][y]='.';if(a[x-1][y]=='.'&&x-1>=0&&x-1<n&&y>=0&&y<n){if(a[x][y+1]=='.'&&x>=0&&x<n&&y+1>=0&&y+1<n){if(a[x+1][y]=='.'&&x+1>=0&&x+1<n&&y>=0&&y<n){if(a[x][y-1]=='.'&&x>=0&&x<n&&y-1>=0&&y-1<n){return ;}}}}for(int i=0;i<4;i++){int xx=x+dx[i],yy=y+dy[i];if(a[xx][yy]=='*'||a[xx][yy]=='#'){dfs_rest(xx,yy);}}
}
int main(){cin>>n;for(int i=0;i<n;i++) for(int j=0;j<n;j++) {cin>>a[i][j];b[i][j]=a[i][j];}for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(b[i][j]=='#') {dfs_all(i,j);res++;}for(int i=0;i<n;i++){for(int j=0;j<n;j++){if(a[i][j]=='.'){for(int k=0;k<4;k++){int x=i+dx[k],y=j+dy[k];if(a[x][y]=='#') a[x][y]='*';}}}}for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(a[i][j]=='#') {dfs_rest(i,j);ans++;}cout<<res-ans<<endl;return 0;
}

BFS(广搜)

模拟队列模板: 

typedef pair<int,int>pii;
int mapp[N][N];
int d[N][N];//每一个点到起点的距离
pii q[N*N];//手写队列
int bfs(){int hh=0,tt=0;q[0]={0,0};memset(d,-1,sizeof d);//距离初始化为-1表示没有走过d[0][0]=0;//表示起点走过了int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};//方向向量while(hh <= tt){//队列不空auto t=q[hh++];//取走队头元素for(int i=0;i<4;i++){//枚举4个方向int x=t.first+dx[i],y=t.second+dy[i];//更新方向if(x>=0&&x<n&&y>=0&&y<m&&mapp[x][y]==0&&d[x][y]==-1){//在边界内并且是空地并且之前没有走过d[x][y]=d[t.first][t.second]+1;//更新距离q[++tt]={x,y};//新坐标入队}}}return d[n-1][m-1];//右下角距起点的距离
}

STL模板:

typedef pair<int,int> pii;
int mapp[N][N],d[N][N];
int bfs(){queue<pii>q;q.push({0,0});memset(d,-1,sizeof d);d[0][0]=0;int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};while(q.size()){auto t=q.front();q.pop();for(int i=0;i<4;i++){int x=t.first+dx[i],y=t.second+dy[i];if(x>=0&&x<n&&y>=0&&y<m&&mapp[x][y]==0&&d[x][y]==-1){d[x][y]=d[t.first][t.second]+1;q.push({x,y});}}}return d[n-1][m-1];
}

打印路径模板:

typedef pair<int,int> pii;
int mapp[N][N],d[N][N];
pii preNode[N][N];//存储每个点的前一个点的坐标,方便追踪路径
int bfs(){queue<pii>q;q.push({0,0});memset(d,-1,sizeof d);d[0][0]=0;int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};while(q.size()){auto t=q.front();q.pop();for(int i=0;i<4;i++){int x=t.first+dx[i],y=t.second+dy[i];if(x>=0&&x<n&&y>=0&&y<m&&mapp[x][y]==0&&d[x][y]==-1){d[x][y]=d[t.first][t.second]+1;preNode[x][y]=t;//记录前驱点,是由t走到(x,y)的q.push({x,y});}}}return d[n-1][m-1];
}
void print_path(){if(d[n-1][m-1]==-1){cout<<"无法抵达终点"<<endl;return ;}vector<pii>path;//从终点遍历追踪for(pii x={n-1,m-1};x!=make_pair(0,0);x=preNode[x.first][x.second]) path.push_back(x);path.push_back({0,0});//加入起点reverse(path.begin(), path.end());//将路径逆序for(auto x:path) cout<<"("<<x.first<<","<<x.second<<")"<<"->";cout<<"终点"<<endl;
}

bfs练习:

B3626 跳跃机器人

一维路径问题 bfs(AC):

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int N=1e6+5;
int n,d[N];
int bfs(){queue<int>q;q.push({1});memset(d,-1,sizeof d);d[1]=0;while(q.size()){auto t=q.front();q.pop();if(t-1>=1&&t-1<=n&&d[t-1]==-1){d[t-1]=d[t]+1;q.push({t-1});}if(t+1>=1&&t+1<=n&&d[t+1]==-1){d[t+1]=d[t]+1;q.push({t+1});}if(2*t>=1&&2*t<=n&&d[2*t]==-1){d[2*t]=d[t]+1;q.push({2*t});}}return d[n];
}
int main(){cin>>n;cout<<bfs()<<endl;return 0;
}

P2802 回家

二维路径问题+多种情况的判断 bfs(AC):

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=10;
int n,m,xbegin,ybegin;
struct point{   //结构体存储当前坐标状态int px,py,pstep,php;//坐标,步数,血量
};
int a[N][N];    //地图
bool flag[N][N];//标记经过鼠标
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
int bfs(int x,int y){queue<point>q;         //注意类型是结构体q.push(point{x,y,0,6});//出发点入队while(q.size()){auto t=q.front();  //取队头元素int x=t.px,y=t.py,step=t.pstep,hp=t.php;//初始化各变量q.pop();           //出队if(a[x][y]==3) return step;//走到家就结束if(hp>1){          //hp<=1时直接死亡for(int i=0;i<4;i++){int xx=x+dx[i],yy=y+dy[i];if(xx>=0&&xx<n&&yy>=0&&yy<m){//不能出界if(a[xx][yy]==1||a[xx][yy]==3){//路和家直接走q.push(point{xx,yy,step+1,hp-1});//入队}if(a[xx][yy]==4&&!flag[xx][yy]){//有鼠标的点最多只能走一次flag[xx][yy]=true;//标记q.push(point{xx,yy,step+1,6});//入队}}}}}return -1;//无解返回-1
}
int main(){cin>>n>>m;for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin>>a[i][j];if(a[i][j]==2) xbegin=i,ybegin=j;}}cout<<bfs(xbegin,ybegin)<<endl;return 0;
}

P1135 奇怪的电梯

 这题会卡纯的dfs,当然也可以搜索每一条路后就更新答案再继续搜索(未AC 64points):

#include<iostream>
using namespace std;
int n,a,b,k[205],ans=1e6,flag[205];
//当前在第x楼,按了cnt次按钮
void dfs(int x,int cnt){if(cnt>=ans) return ;if(x==b){ans=min(ans,cnt);return ;}flag[x]=1;if(x+k[x]<=n&&flag[x+k[x]]==0){ //上楼flag[x+k[x]]=1;dfs(x+k[x],cnt+1);flag[x+k[x]]=0;}if(x-k[x]>=1&&flag[x-k[x]]==0){ //下楼flag[x-k[x]]=1;dfs(x-k[x],cnt+1);flag[x-k[x]]=0;}
}
int main(){cin>>n>>a>>b;for(int i=1;i<=n;i++) cin>>k[i];dfs(a,0);if(ans==1e6) {cout<<"-1"<<endl; return 0;}cout<<ans<<endl;return 0;
}

bfs(AC):

#include<iostream>
#include<queue>
using namespace std;
const int N=205;
int n,A,B,lift[N];
bool flag[N];
//标记数组作用是保证当前位置没有来过,因为如果回到原来经过的位置,那么就会一直重复
struct point{int loc,ans;//位置,当前已经走的步数
};
int bfs(int a,int b){queue<point>q;q.push(point{a,0});while(q.size()){auto t=q.front();int location=t.loc,step=t.ans;q.pop();if(location==b) return step;//到达终点if(location+lift[location]<=n){//可以向上if(!flag[location+lift[location]]){//并且该位置没有来过flag[location+lift[location]]=true;q.push(point{location+lift[location],step+1});}}if(location-lift[location]>=1){//可以向下if(!flag[location-lift[location]]){//并且该位置没有来过flag[location-lift[location]]=true;q.push(point{location-lift[location],step+1});}}}return -1;
}
int main(){cin>>n>>A>>B;for(int i=1;i<=n;i++) cin>>lift[i];cout<<bfs(A,B)<<endl;return 0;
}

P1747 好奇怪的游戏

这题注意初始化flag标记数组,并且把数组开大一点就没问题了

bfs(AC):

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=50;
int x1,y1,x2,y2;
int dx[12]={-2,-2,-1,-2,1,-2,2,-1,2,1,2,2};
int dy[12]={-2,-1,-2,1,-2,2,-2,2,-1,2,1,2};
bool flag[N][N];
struct point{int px,py,pstep;//坐标,步数
};
int bfs(int a,int b){queue<point>q;q.push(point{a,b,0});memset(flag,0,sizeof flag);flag[a][b]=true;while(q.size()){auto t=q.front();q.pop();int x=t.px,y=t.py,step=t.pstep;if(x==1&&y==1) return step;for(int i=0;i<12;i++){int xx=x+dx[i],yy=y+dy[i];if(xx>=1&&yy>=1){if(!flag[xx][yy]){flag[xx][yy]=true;q.push(point{xx,yy,step+1});}}}}
}
int main(){cin>>x1>>y1>>x2>>y2;cout<<bfs(x1,y1)<<endl;cout<<bfs(x2,y2)<<endl;return 0;
}

P1443 马的遍历

方法类似,只需要额外开一个二维答案数组存储步数即可

bfs(AC):

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=405;
int n,m,x,y;
int dx[8]={-2,-1,-2,1,-1,2,1,2};
int dy[8]={-1,-2,1,-2,2,-1,2,1};
int ans[N][N];//答案矩阵
bool flag[N][N];
struct point{int px,py;//坐标
};
void bfs(int a,int b){ans[a][b]=0;flag[a][b]=true;queue<point>q;q.push(point{a,b});while(q.size()){auto t=q.front();q.pop();int x=t.px,y=t.py;for(int i=0;i<8;i++){int xx=x+dx[i],yy=y+dy[i];if(xx>=1&&xx<=n&&yy>=1&&yy<=m){if(!flag[xx][yy]){flag[xx][yy]=true;q.push(point{xx,yy});ans[xx][yy]=ans[x][y]+1;}}}}return ;
}
int main(){cin>>n>>m>>x>>y;memset(ans,-1,sizeof ans);memset(flag,0,sizeof flag);bfs(x,y);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cout<<ans[i][j]<<" ";}cout<<endl;}return 0;
}

P1746 离开中山路

bfs(AC):

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=1005;
int n,x1,x2,y1,y2;
char a[N][N];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
bool flag[N][N];
struct point{int px,py,ps;
};
int bfs(int bx,int by,int ex,int ey){queue<point>q;q.push(point{bx,by,0});flag[bx][by]=true;while(q.size()){auto t=q.front();int x=t.px,y=t.py,step=t.ps;q.pop();if(x==ex&&y==ey) return step;for(int i=0;i<4;i++){int xx=x+dx[i],yy=y+dy[i];if(xx>=1&&xx<=n&&yy>=1&&yy<=n){if(a[xx][yy]=='0'){if(!flag[xx][yy]){flag[xx][yy]=true;q.push(point{xx,yy,step+1});}}}}}return -1;
}
int main(){cin>>n;for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>a[i][j];cin>>x1>>y1>>x2>>y2;cout<<bfs(x1,y1,x2,y2)<<endl;return 0;
}

P3395 路障

这题整体思路不变,唯一要加的是唯一需要注意的是路障的处理,可开一个block数组存放在(x,y)位置路障将在什么时候放下,对于没有路障的点,直接走过,对于有路障的点,判断时间即可

bfs(AC):

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=1005;
int T,n,a[N][N],block[N][N];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
bool flag[N][N];
struct point{int px,py,pt;//坐标,时间
};
bool bfs(){queue<point>q;q.push(point{1,1,0});flag[1][1]=true;while(!q.empty()){auto t=q.front();int x=t.px,y=t.py,timee=t.pt;q.pop();if(x==n&&y==n) return true;timee++;for(int i=0;i<4;i++){int xx=x+dx[i],yy=y+dy[i];if(xx>=1&&xx<=n&&yy>=1&&yy<=n){if(a[xx][yy]==0&&!flag[xx][yy]){flag[xx][yy]=true;if(!block[xx][yy]||timee<=block[xx][yy]){q.push(point{xx,yy,timee});}}}}}return false;
}
int main(){cin>>T;while(T--){memset(flag,0,sizeof flag);memset(block,0,sizeof block);memset(a,0,sizeof a);cin>>n;for(int i=1;i<=2*n-2;i++){int a1,b1;cin>>a1>>b1;block[a1][b1]=i;}if(bfs()) cout<<"Yes"<<endl;else cout<<"No"<<endl;}return 0;
}

P8673 [蓝桥杯 2018 国 C] 迷宫与陷阱

和 P2802 回家 类似,

三维状态数组+多种情况判断 bfs(AC):

#include<iostream>
#include<cstring>
#include<queue> 
using namespace std;
const int N=1005;
int n,k;
char a[N][N];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
//flag[x][y][z]:在剩余z个无敌时间时,有没有经过(x,y)
bool flag[N][N][11];
struct point{int px,py,ps,pk;//坐标,当前走的步数,剩余无敌的步数
};
int bfs(){queue<point>q;q.push({1,1,0,0});flag[1][1][0]=true;while(!q.empty()){auto t=q.front();q.pop();int x=t.px,y=t.py,step=t.ps,temp=t.pk;if(x==n&&y==n) return step;//到达终点,直接结束for(int i=0;i<4;i++){int xx=x+dx[i],yy=y+dy[i];if(xx>=1&&xx<=n&&yy>=1&&yy<=n){//保证边界if(a[xx][yy]!='#'){//墙是永远不可能经过的//当前是未使用过的道具if(a[xx][yy]=='%'&&!flag[xx][yy][k]){flag[xx][yy][k]=true;q.push({xx,yy,step+1,k});}//当前状态是无敌,道路和陷阱都可以走if(temp>0&&!flag[xx][yy][temp-1]){flag[xx][yy][temp-1]=true;q.push({xx,yy,step+1,temp-1});}//当前状态不是无敌,道路可以走if(temp==0&&a[xx][yy]=='.'&&!flag[xx][yy][0]){flag[xx][yy][0]=true;q.push({xx,yy,step+1,0});}}}}}return -1;
}
int main(){cin>>n>>k;for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>a[i][j];cout<<bfs()<<endl;return 0;
}

P1141 01迷宫

暴力bfs (超时未AC 70points):

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=1e3+5;
char a[N][N];
bool flag[N][N];
int n,m,ans;
int dx[4]={-1,0,1,0};
int dy[4]={0,-1,0,1};
int bfs(int tx,int ty){ans=1;flag[tx][ty]=1;queue<pair<int,int>>q;q.push({tx,ty});while(!q.empty()){auto t=q.front();int x=t.first,y=t.second;q.pop();for(int i=0;i<4;i++){int xx=x+dx[i],yy=y+dy[i];if(xx>=1&&xx<=n&&yy>=1&&yy<=n){if(!flag[xx][yy]&&a[xx][yy]!=a[x][y]){flag[xx][yy]=1;ans++;q.push({xx,yy});}}}}return ans;
}
int main(){cin>>n>>m;for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>a[i][j];while(m--){int ax,bx;cin>>ax>>bx;memset(flag,0,sizeof flag);cout<<bfs(ax,bx)<<endl;}return 0;
}

优化思路:

联通块上每一个点的答案等于该联通块的数目

注意这里的联通块指的是四个方向上0,1相间隔的联通块,如下图,在搜 a[1][2] 时会经过6个点,而这6个点的答案是一样的,都是6,因此通过搜完联通块直接给联通块上的所有点存答案即可

 

因此可以考虑 dfs+记忆化搜索(AC):

#include<iostream>
using namespace std;
const int N=1e3+5;
char a[N][N];//地图
int ans[N][N];//答案数组为0表示没有搜过,大于0表示答案
int temp[N*N][2];//记忆化,存储坐标数组
int n,m,res;
int dx[4]={-1,0,1,0};
int dy[4]={0,-1,0,1};
void dfs(int x,int y){res++;//搜到,答案自增//记忆化:存储坐标temp[res][0]=x;temp[res][1]=y;//ans数组当前只起标记作用ans[x][y]=1;for(int i=0;i<4;i++){int xx=x+dx[i],yy=y+dy[i];if(xx>=1&&xx<=n&&yy>=1&&yy<=n){if(a[x][y]!=a[xx][yy]){if(!ans[xx][yy]){dfs(xx,yy);}}}}return ;
}
int main(){cin>>n>>m;for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>a[i][j];while(m--){int ax,bx;cin>>ax>>bx;res=0;//已经存储过答案直接输出if(ans[ax][bx]) cout<<ans[ax][bx]<<endl;else{//否则搜素dfs(ax,bx);//记忆化:把路径上所有点的答案存储//ans数组正式记录所有答案for(int i=1;i<=res;i++)ans[temp[i][0]][temp[i][1]]=res;cout<<res<<endl;}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/322649.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【华为】AC直连二层组网隧道转发实验配置

【华为】AC直连二层组网隧道转发实验配置 实验需求拓扑配置AC数据规划表 AC的配置顺序AC1基本配置(二层通信)AP上线VAP组关联--WLAN业务流量 LSW1AR1STA获取AP的业务流量 配置文档 实验需求 AC组网方式&#xff1a;直连二层组网。 业务数据转发方式&#xff1a;隧道转发。 DHC…

MacOS搭建docker本地私有镜像库

相关环境 macOS: bigsur 11.7.8 docker desktop: 4.22.0 docker engine: 24.0.5 准备工作 本机已经安装好docker desktop&#xff0c;未安装的自行参考其他教程。如果不能翻墙&#xff0c;可以修改本地的镜像地址&#xff0c;可在docker desktop 设置中的docker engine中修…

Excel Module: Iteration #1 EasyExcel生成下拉列表模版时传入动态参数查询下拉数据

系列文章 EasyExcel生成带下拉列表或多级级联列表的Excel模版自定义校验导入数据(修订) 目录 系列文章前言仓库一、实现1.1 下拉元数据对象1.2 构建下拉元数据的映射关系1.3 框架方式1.3.1 框架实现1.3.2 框架用例模版类加载下拉业务导出接口 1.4 EasyExcel方式1.4.1 EasyExce…

Redis(Jedis和SpringBoot整合Redis)

文章目录 1.Jedis1.介绍2.环境配置1.创建maven项目2.pom.xml引入依赖3.新建一个包并创建一个文件 3.Jedis远程连接到Redis1.Redis放到服务器可以连接的前提条件2.为Redis设置密码1.编辑配置文件2.找到 requirepass3.设置密码为root4.重启Redis&#xff0c;在shutdown的时候报错…

计算机网络——Dijkstra路由算法

实验目的 实现基于 Dijkstra 算法的路由软件 实验内容 网络拓扑如图所示 实验过程 先编写开辟应该图的空间&#xff0c;然后给点映射数字&#xff0c;构建图。程序获取用户输入的学号&#xff0c;构建图中边的权值。接下来程序从用户输入获取最短路径的搜索起点&#xff0…

基于C++基础的函数模块

在C中&#xff0c;函数是一段封装了某种功能的代码块&#xff0c;可以在程序的不同地方重复使用。函数定义包含如下组成部分&#xff1a; 函数头&#xff1a;函数头包括函数返回类型、函数名和参数列表。函数返回类型规定了函数返回的数据类型&#xff0c;函数名是函数的唯一标…

Java_从入门到JavaEE_11

一、抽象类及抽象方法 1.认识抽象类及抽象方法 应用场景&#xff1a;当一个方法必须在父类中出现&#xff0c;但是这个方法又不好实现&#xff0c;就把该方法变成抽象方法&#xff0c;交给非抽象的子类去实现 实例&#xff1a; //抽象类 public abstract class 类名{//抽象方…

5月将有17款游戏发布,腾讯的《地下城与勇士:起源》备受关注

易采游戏网5月8日消息&#xff0c;本月将有17款新游戏预计上线&#xff0c;其中14款已正式定档&#xff0c;游戏市场即将迎来一场盛大的狂欢。在众多备受期待的游戏中&#xff0c;有两款游戏尤其引人注目&#xff0c;它们分别是来自库洛和腾讯的《地下城与勇士&#xff1a;起源…

学习方法的重要性

原贴&#xff1a;https://www.cnblogs.com/feily/p/13999204.html 原贴&#xff1a;https://36kr.com/p/1236733055209095 1、 “一万小时定律”的正确和误区 正确&#xff1a; 天才和大师的非凡&#xff0c;不是真的天资超人一等&#xff0c;而是付出了持续不断的努力&…

武汉星起航:成功挂牌上股交,优势尽显启新程,共绘创业投资梦

在金秋十月的尾声&#xff0c;武汉星起航电子商务有限公司迎来了一个重要的历史时刻——于2023年10月30日在上海股权托管交易中心成功挂牌展示&#xff0c;正式登陆资本市场。这一里程碑式的跨越&#xff0c;不仅标志着武汉星起航在跨境电商领域的卓越实力&#xff0c;更彰显了…

MAC地址冲突案例

1、问题描述&#xff1a;WiFi-A网段做了策略路由&#xff0c;引流到另一台设备&#xff0c;连接WiFi-A后通过DHCP获取到了地址却无法上网&#xff0c;此时排查思路是什么&#xff1f; &#xff08;1&#xff09;、排查方法&#xff1a; 看到网关通信是否正常 第一次获取地址正…

mysql中varchar与bigint直接比较会导致精度丢失以至于匹配到多行数据

在mysql中&#xff0c;我们都知道如果一个索引字段使用了函数或者计算那么查询的时候索引会失效&#xff0c;可是我相信在联表的时候我们只会关注两个表关联字段是否都创建了索引&#xff0c;却没有关注过这两个字段的类型是否一致&#xff0c;如果不一致的话索引是会失效的&am…

Windows系统完全卸载删除 Node.js (包含控制面板找不到node.js选项情况)

1.打开cmd命令行窗口&#xff0c;输入npm cache clean --force 回车执行 2.打开控制面板&#xff0c;在控制面板中把Node.js卸载 移除之后检查环境变量是否也移除&#xff1a;点击Path&#xff0c;点击编辑。 把环境变量中和node有关的全部移除&#xff0c;然后点击确定。 3.重…

WPF之创建无外观控件

1&#xff0c;定义无外观控件。 定义默认样式&#xff0c;在其静态构造函数中调用DefaultStyleKeyProperty.OverrideMetadata()。 //设置默认样式DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker))); 在项目…

Android C++ 开发调试 LLDB 工具的使用

文章目录 调试环境准备基础命令Breakpoint CommandsWatchpoint CommandsExamining VariablesEvaluating ExpressionsExamining Thread StateExecutable and Shared Library Query Commands 参考&#xff1a; Android 中在进行 NDK 开发的时候&#xff0c;我们经常需要进行 C 代…

为什么互联网行业这两年突然就不行了?

前言&#xff1a; 本人正好最近十年基本都是在互联网行业&#xff0c;真正算是经历了行业的起伏波澜&#xff0c;火的时候被烤的滚烫&#xff0c;冷的时候被冻得冰凉&#xff0c;都算是切身感受到了。 首先&#xff0c;互联网行业的“行”与“不行”&#xff0c;还是一个相对…

短剧新纪元:引领潮流的短剧小程序开发,一触即达精彩世界

在信息爆炸的时代&#xff0c;短视频以其短小精悍、内容丰富的特点迅速崛起&#xff0c;成为人们日常生活中不可或缺的一部分。然而&#xff0c;短视频的短暂与碎片化&#xff0c;有时难以满足观众对完整故事的需求。为此&#xff0c;我们倾力打造了一款短剧小程序&#xff0c;…

如何修复连接失败出现的错误651?这里提供修复方法

错误651消息在Windows 7到Windows 11上很常见&#xff0c;通常会出现在一个小的弹出窗口中。实际文本略有不同&#xff0c;具体取决于连接问题的原因&#xff0c;但始终包括文本“错误651”。 虽然很烦人&#xff0c;但错误651是一个相对较小的问题&#xff0c;不应该导致计算…

AI图书推荐:ChatGPT在真实商业世界中的应用

《ChatGPT在真实商业世界中的应用》 (Unleashing The Power of ChatGPT: A Real World Business Applications)首先概述了ChatGPT及其在对话式人工智能领域的影响。接着&#xff0c;你将深入了解ChatGPT的技术方面&#xff0c;理解机器学习算法和自然语言处理如何在后台工作。然…

Android进阶之路 - 静态会员进度条

年后这个新版本加入了VIP模块&#xff0c;有幸正好由我来负责&#xff0c;可以再积累一下这方面的知识。 那段时间看了一本书&#xff0c;书中说到初级码农的特性之一就是完全集中于某些功能&#xff0c;忽略了了很多成长机会&#xff0c;所以重复性劳作带来的成长值有限&#…