2019.1.23 01迷宫
不难发现因为格子能走的判定是双向的
所以所有连在一起的格子能走到的格子个数都是一样的
也就是说只要知道了一个格子能走到多少格子这些能走到的格子的解都可以求出来
于是我们想到了并查集
对于二维的并查集可以使用映射的方法
也就是将(i,j)映射到i*n+j
代码
#include<iostream> #include<cstdio> using namespace std; int n,m,p,q; char map[1050][1050]; int fa[1050][1050],book[150000000]; int fi(int p,int q)//查找函数 { if(fa[p][q]==p*10000+q)return p*10000+q; return fa[p][q]=fi(fa[p][q]/10000,fa[p][q]%10000);//路径压缩,注意fi函数里的参数是逆映射 } void u(int p1,int q1,int p2,int q2)//合并函数 { if(fi(p1,q1)!=fi(p2,q2)) { if(fa[p2][q2]>fa[p1][q1])fa[fi(p2,q2)/10000][fi(p2,q2)%10000]=fa[fi(p1,q1)/10000][fi(p1,q1)%10000]; else fa[fi(p1,q1)/10000][fi(p1,q1)%10000]=fa[fi(p2,q2)/10000][fi(p2,q2)%10000]; }//特别注意合并祖先的时候合并的是两个节点父亲的祖先,因为路径压缩再加上合并之后的树是三层的树 return; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { cin>>map[i][j]; fa[i][j]=i*10000+j; } getchar(); } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(j<n&&(int(map[i][j]-48))^(int(map[i][j+1]-48))==1) u(i,j,i,j+1); if(i<n&&(int(map[i][j]-48))^(int(map[i+1][j]-48))==1) u(i,j,i+1,j); }//每次搜索向右、向下,若可以走则合并 } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { ++book[fi(i,j)]; fa[i][j]=fi(i,j); } } for(int i=1;i<=m;i++) { scanf("%d%d",&p,&q); printf("%d\n",book[fa[p][q]]); } return 0; }
/*====年轻人,瞎搞是出不了省一的,这就是现实====*/
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步