01迷宫-做题报告

1|001迷宫

2018-10-19

看到这道题就无脑bfs了,然后拿了50分。然而并不知道怎么优化。

#include<bits/stdc++.h> using namespace std; int n,m; int mmp[5000][5000]; int x,y; int vis[5000][5000]; int dx[]={1,0,-1,0}; int dy[]={0,1,0,-1}; int ans=0; struct node{ int x,y; }; queue<node> Q; inline int bfs(int x,int y){ node s; s.x=x,s.y=y; Q.push(s); vis[x][y]=1; ans++; while(!Q.empty()){ node k=Q.front(); Q.pop(); for(int i=0;i<4;i++){ node zzq; int sx=k.x+dx[i],sy=k.y+dy[i]; //printf("sx=%d sy=%d\n",sx,sy); if(sx<=n&&sx>=1&&sy<=n&&sy>=1&&!vis[sx][sy]&&mmp[sx][sy]!=mmp[k.x][k.y]){ //printf("SSR::sx=%d sy=%d\n",sx,sy); vis[sx][sy]=1; ans++; zzq.x=sx,zzq.y=sy; Q.push(zzq); } } } } int main(){ ios::sync_with_stdio(false); cin>>n>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ char c; cin>>c; mmp[i][j]=c-'0'; } } for(int i=1;i<=m;i++){ cin>>x>>y; ans=0; bfs(x,y); memset(vis,0,sizeof vis); cout<<ans<<endl; } return 0; }

我觉得超时主要的原因是每次输入都要询问废话,还有每次都要用memset来清空vis数组(但是不知道要怎么改啊啊啊)

1|0然后我看了很多篇题解,终于发现了一篇适合我的:

1|0大概的思路是记忆化

  1. 设num为第num的次输入。则anser[num]就是第num次输入的答案

  2. 把原来用来标记的vis数组的赋值步骤vis[sx][sy]=1改成vis[sx][sy]=num;因为只要在bfs(x,y)中搜索到了sx,sy;那么根据题目的性质bfs(sx,sy)和bfs(x,y)的答案是一样的;记得在开头vis[x][y]=num

  3. 最后在每一次bfs的结尾把答案存入anser[num]中,下一次搜索时如果vis[x][y]有值那么直接输出anser[vis[x][y]]即可。

    1|0附上我的AC代码

    #include<bits/stdc++.h> using namespace std; int n,m; int mmp[5000][5000]; int x,y; int vis[5000][5000]; int anser[5000000]; int dx[]={1,0,-1,0}; int dy[]={0,1,0,-1}; int ans=0; struct node{ int x,y; }; queue<node> Q; int num=0; inline void bfs(int x,int y){ ans=0; node s; num++; if(vis[x][y]){ cout<<anser[vis[x][y]]<<endl; return ; } s.x=x,s.y=y; Q.push(s); vis[x][y]=num; ans++; while(!Q.empty()){ node k=Q.front(); Q.pop(); for(int i=0;i<4;i++){ node zzq; int sx=k.x+dx[i],sy=k.y+dy[i]; //printf("sx=%d sy=%d\n",sx,sy); if(sx<=n&&sx>=1&&sy<=n&&sy>=1&&!vis[sx][sy]&&mmp[sx][sy]!=mmp[k.x][k.y]){ //printf("SSR::sx=%d sy=%d\n",sx,sy); ans++; vis[sx][sy]=num; zzq.x=sx,zzq.y=sy; Q.push(zzq); } } } anser[num]=ans; cout<<ans<<endl; return ; } int main(){ ios::sync_with_stdio(false); cin>>n>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ char c; cin>>c; mmp[i][j]=c-'0'; } } for(int i=1;i<=m;i++){ cin>>x>>y; bfs(x,y); } return 0; }

1|1现在是2018/12/06 我又重做了一遍这道题。

这次完全是自己的思想

我看了下样例发现了一个规律,你每次搜索时搜索到的每一个点的答案都是一样的,于是我每次dfs完直接把搜到的点的答案都更新一边就可以了。

1|2code

#include <cstdio> #include <iostream> #include <cstring> #include <vector> using std::vector; using std::pair; using std::cin; inline void read(int &x) { x=0;char ch=0;bool sign=false; while(ch < '0' || ch > '9') { sign|=(ch == '-'); ch=getchar(); } while(!(ch < '0' || ch > '9')) { x=x*10+(ch^48); ch=getchar(); } x=sign ? -x : x; } const int dx[4]={0,0,-1,1}, dy[4]={1,-1,0,0}; int n,m; int x,y; int dis[1220][1102]; char map[1300][1200]; int vis[1232][2323]; int p,k; vector< pair<int , int> > ans; inline void dfs(int x,int y) { //printf("map[%d][%d]=%d \n",x,y,map[x][y]); if(dis[x][y] > 1){ return ; } for(int i=0; i<4; i++) { int sx=x+dx[i],sy=y+dy[i]; //printf("map[%d][%d]=%d \n",sx,sy,map[sx][sy]); if(sx<1 || sx>n || sy<1 || sy>n || vis[sx][sy] || map[sx][sy] == map[x][y])continue; vis[sx][sy]=1; ans.push_back({sx,sy}); dfs(sx,sy); dis[x][y]+=dis[sx][sy]; } } int main() { read(n);read(m); for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { dis[i][j]=1; cin>>map[i][j]; } //getchar(); } for(int i=1; i<=m; i++) { //memset(vis, 0 ,sizeof vis); read(x),read(y); /*if(dis[x][y] > 1) { printf("%d\n",dis[x][y]); } else {*/ ans.clear(); vis[x][y]=1; p=x,k=y; dfs(x,y); for(int i=0; i<ans.size(); i++) { //printf("x=%d y=%d ans[%d][%d]=%d\n",x,y,ans[i].first,ans[i].second,dis[x][y]); dis[ans[i].first][ans[i].second]=std::max(dis[x][y],dis[ans[i].first][ans[i].second]); } printf("%d\n",dis[x][y]); //} } return 0; }

之前忘了每次询问都要ans.clear();了,然后还一度怀疑自己的做法是错的。。。


__EOF__

本文作者Kdlyh
本文链接https://www.cnblogs.com/kdlyh/p/17777013.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   加固文明幻景  阅读(5)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示