P1141零一迷宫
这是一道对于除了我之外其他人都十分简单的搜索题,我终于在这个夜里搞会了。
首先其问可以到达多少个点,并不是走一次可以最多经过几个点,这就解释了为什么不需要回溯,并且递归边界则是让其全部走完即可。于是便写了程序,然后TLE 了三个点,因为时间复杂度可能会达到5e8 O(1000+4000)*100000。其实早就知道要用联通块去写,到处翻题解,终于找到了一篇属于我的,感谢那位dalao,还有lyx和两位讨论版大佬。首先我们要知道只要是两个点联通,那么这两个点能到达的点的数量是一样的——所以我们只需要搜索有几个联通块,然后这个联通块的格子里能到达的格子数量就是这个联通块所包含的格子数!然后我们就需要一个k记录有多少个联通块,num[k]记录每个联通块的格子数量,那么book[x][y]则表示他所属于的联通块即可,=0的话还是说明他没有被遍历过,k++搜索他。
1.空间&时间复杂度一定计算仔细
2.正确理解题意,不要总是套回溯的模板,结果这个题,,,
3.联通块要熟练掌握,但是注意先决条件,思考是不是同一个块里的数量相同
4.学习中,有困难也去突破,回头发现其实并不难
代码(有点玄学的是把数组开大了一位之后就90-100了)
#include<bits/stdc++.h> using namespace std; int n,m; int book[1005][1005]; char mp[1005][1005]; int ans[1000005],num[1000005];//存答案所在联通块以及联通块的格子数量 int k=0;//联通块数量 int step=1; int dx[4]={0,-1,0,1};//右下左上 int dy[4]={1,0,-1,0}; void dfs(int x,int y,int k){ book[x][y]=k; for(int i=0;i<=3;i++){ int tx=dx[i]+x; int ty=dy[i]+y; if(mp[tx][ty]!=mp[x][y]){ if(tx>0&&ty>0&&tx<=n&&ty<=n&&book[tx][ty]==0){ step++;//格子数量++ dfs(tx,ty,k);//继续往下搜索 } } } } int main(){ cin>>n>>m; for(int i=1;i<=n;i++){//读入 for(int j=1;j<=n;j++){ cin>>mp[i][j]; book[i][j]=0; } } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(book[i][j]==0){ k++; step=1; dfs(i,j,k); num[k]=step; } } } for(int i=1;i<=m;i++){ int x,y; cin>>x>>y; ans[i]=num[book[x][y]]; } for(int i=1;i<=m;i++){ cout<<ans[i]<<endl; } return 0; }
待到oi十一月,我花开后百花杀。