zoukankan      html  css  js  c++  java
  • 洛谷P1141 01迷宫(图的遍历搜素递归dfs或bfs,连痛块回溯更新问题,记忆化或者并查集根结点)

    题目链接:https://www.luogu.org/problemnew/show/P1141

    做这到题有2点需要注意:

    1.发现每个连通的点他们的答案都是一样的!这个很重要,不然后面没法做。

    2.接下来就是找连通块了。

    题目相当于求连通块,这个比较简单,但加上了m次询问后就是难点所在,很容易超时。所以必须结合1规律做了,他们答案都是一样的!

    一定要注意:使用2和3时,关键注意memset(vis,0,sizeof(vis))都不用了,否则还超时(搜索到底什么时候 回溯更新 搞清楚!)

    如果搜索有问题,那怎么写都超时!

    1.T3,原始,每次询问都搜一遍,70分

     1 #include <iostream>
     2 #include <string>
     3 #include <algorithm>
     4 #include <iomanip>
     5 #include <cstdio>
     6 #include <cstring>
     7 #include <cmath>
     8 using namespace std;
     9 typedef long long ll;
    10 typedef unsigned long long ull;
    11 const int maxn=1005;
    12 char maze[maxn][maxn];
    13 int vis[maxn][maxn];
    14 int n,m;
    15 int sx,sy;
    16 int ans;
    17 
    18 void so(int x,int y)
    19 {
    20     //
    21     if(y+1<=n && maze[x][y+1]!=maze[x][y] && vis[x][y+1]==0) { ans++; vis[x][y+1]=1; so(x,y+1); }
    22     //
    23     if(x+1<=n && maze[x+1][y]!=maze[x][y] && vis[x+1][y]==0) { ans++; vis[x+1][y]=1; so(x+1,y); }
    24     //
    25     if(x-1>=1 && maze[x-1][y]!=maze[x][y] && vis[x-1][y]==0) { ans++; vis[x-1][y]=1; so(x-1,y); }
    26     //
    27     if(y-1>=1 && maze[x][y-1]!=maze[x][y] && vis[x][y-1]==0) { ans++; vis[x][y-1]=1; so(x,y-1); }
    28 }
    29 
    30 int main()
    31 {
    32     ios::sync_with_stdio(false); cin.tie(0);
    33 
    34     cin>>n>>m;
    35     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>maze[i][j];
    36 
    37     while(m--)
    38     {
    39         cin>>sx>>sy;
    40 
    41         memset(vis,0,sizeof(vis));
    42         ans=1;
    43         vis[sx][sy]=1;
    44         so(sx,sy);
    45 
    46         cout<<ans<<endl;
    47     }
    48 
    49     return 0;
    50 }

    2.将每次找到的联通块都赋予答案,下次就不用再搜了直接输入(本质:最后遍历一遍联通块赋值,相当于记忆化保存),100分

     1 #include <iostream>
     2 #include <string>
     3 #include <algorithm>
     4 #include <iomanip>
     5 #include <cstdio>
     6 #include <cstring>
     7 #include <cmath>
     8 using namespace std;
     9 typedef long long ll;
    10 typedef unsigned long long ull;
    11 const int maxn=1005;
    12 char maze[maxn][maxn];
    13 int vis[maxn][maxn];
    14 int Ans[maxn][maxn];
    15 int n,m;
    16 int sx,sy;
    17 int ans,anscnt;
    18 int p=0,lastp=0;
    19 struct px
    20 {
    21     int x;
    22     int y;
    23 }T[maxn*maxn+5];
    24 
    25 void so(int x,int y)
    26 {
    27     //
    28     if(y+1<=n && maze[x][y+1]!=maze[x][y] && vis[x][y+1]==0) { ans++; vis[x][y+1]=1; T[++p].x=x; T[p].y=y+1; so(x,y+1); }
    29     //
    30     if(x+1<=n && maze[x+1][y]!=maze[x][y] && vis[x+1][y]==0) { ans++; vis[x+1][y]=1; T[++p].x=x+1; T[p].y=y; so(x+1,y); }
    31     //
    32     if(x-1>=1 && maze[x-1][y]!=maze[x][y] && vis[x-1][y]==0) { ans++; vis[x-1][y]=1; T[++p].x=x-1; T[p].y=y; so(x-1,y); }
    33     //
    34     if(y-1>=1 && maze[x][y-1]!=maze[x][y] && vis[x][y-1]==0) { ans++; vis[x][y-1]=1; T[++p].x=x; T[p].y=y-1; so(x,y-1); }
    35 }
    36 
    37 int main()
    38 {
    39     ios::sync_with_stdio(false); cin.tie(0);
    40 
    41     cin>>n>>m;
    42     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>maze[i][j];
    43 
    44     while(m--)
    45     {
    46         cin>>sx>>sy;
    47 
    48         if(Ans[sx][sy]==0 && anscnt<n*n)
    49         {
    50             //memset(vis,0,sizeof(vis));
    51             ans=1;
    52             vis[sx][sy]=1;
    53             so(sx,sy);
    54 
    55             T[++p].x=sx; T[p].y=sy;
    56             for(int i=lastp+1;i<=p;i++)
    57             {
    58                 int x=T[i].x,y=T[i].y;
    59                 Ans[x][y]=ans;
    60                 anscnt++;
    61             }
    62             lastp=p;
    63 
    64             cout<<ans<<endl;
    65         }
    66         else cout<<Ans[sx][sy]<<endl;
    67     }
    68 
    69     return 0;
    70 }

    3.找出父结点代替(本质:集合问题并查集,找出一个代表即可),100分

     1 #include <iostream>
     2 #include <string>
     3 #include <algorithm>
     4 #include <iomanip>
     5 #include <cstdio>
     6 #include <cstring>
     7 #include <cmath>
     8 using namespace std;
     9 typedef long long ll;
    10 typedef unsigned long long ull;
    11 const int maxn=1005;
    12 char maze[maxn][maxn];
    13 int vis[maxn][maxn];
    14 int fax[maxn][maxn],fay[maxn][maxn];
    15 int Ans[maxn][maxn];
    16 int n,m;
    17 int sx,sy;
    18 int ans;
    19 
    20 void so(int x,int y)
    21 {
    22     //
    23     if(y+1<=n && maze[x][y+1]!=maze[x][y] && vis[x][y+1]==0) { ans++; vis[x][y+1]=1; fax[x][y+1]=sx; fay[x][y+1]=sy; so(x,y+1); }
    24     //
    25     if(x+1<=n && maze[x+1][y]!=maze[x][y] && vis[x+1][y]==0) { ans++; vis[x+1][y]=1; fax[x+1][y]=sx; fay[x+1][y]=sy; so(x+1,y); }
    26     //
    27     if(x-1>=1 && maze[x-1][y]!=maze[x][y] && vis[x-1][y]==0) { ans++; vis[x-1][y]=1; fax[x-1][y]=sx; fay[x-1][y]=sy; so(x-1,y); }
    28     //
    29     if(y-1>=1 && maze[x][y-1]!=maze[x][y] && vis[x][y-1]==0) { ans++; vis[x][y-1]=1; fax[x][y-1]=sx; fay[x][y-1]=sy; so(x,y-1); }
    30 }
    31 
    32 int main()
    33 {
    34     ios::sync_with_stdio(false); cin.tie(0);
    35 
    36     for(int i=0;i<=maxn-1;i++) for(int j=0;j<=maxn-1;j++) Ans[i][j]=-1;
    37 
    38     cin>>n>>m;
    39     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { cin>>maze[i][j]; }
    40 
    41     while(m--)
    42     {
    43         cin>>sx>>sy;
    44 
    45         if(Ans[fax[sx][sy]][fay[sx][sy]]==-1)
    46         {
    47             fax[sx][sy]=sx;
    48             fay[sx][sy]=sy;
    49             //memset(vis,0,sizeof(vis));
    50             ans=1;
    51             vis[sx][sy]=1;
    52             so(sx,sy);
    53 
    54             Ans[sx][sy]=ans;
    55             cout<<Ans[sx][sy]<<endl;
    56         }
    57         else cout<<Ans[fax[sx][sy]][fay[sx][sy]]<<endl;
    58     }
    59 
    60     return 0;
    61 }

    4.紫书上找连通块最好方法:直接给每个相通的所有连通块一个编号根结点(很nice的方法,并查集集合祖先结点思想!)

     1 #include <iostream>
     2 #include <string>
     3 #include <algorithm>
     4 #include <iomanip>
     5 #include <cstdio>
     6 #include <cstring>
     7 #include <cmath>
     8 using namespace std;
     9 typedef long long ll;
    10 typedef unsigned long long ull;
    11 const int maxn=1005;
    12 char maze[maxn][maxn];
    13 int vis[maxn][maxn];
    14 int Ans[maxn*maxn];
    15 int n,m;
    16 int sx,sy;
    17 int ans;
    18 int cnt;//直接给每个相通的所有连通块一个编号根结点(很nice的方法,并查集集合祖先结点思想!)
    19 
    20 void so(int x,int y,int t)
    21 {
    22     //
    23     if(y+1<=n && maze[x][y+1]!=maze[x][y] && vis[x][y+1]==0) { ans++; vis[x][y+1]=cnt; so(x,y+1,t); }
    24     //
    25     if(x+1<=n && maze[x+1][y]!=maze[x][y] && vis[x+1][y]==0) { ans++; vis[x+1][y]=cnt; so(x+1,y,t); }
    26     //
    27     if(x-1>=1 && maze[x-1][y]!=maze[x][y] && vis[x-1][y]==0) { ans++; vis[x-1][y]=cnt; so(x-1,y,t); }
    28     //
    29     if(y-1>=1 && maze[x][y-1]!=maze[x][y] && vis[x][y-1]==0) { ans++; vis[x][y-1]=cnt; so(x,y-1,t); }
    30 }
    31 
    32 int main()
    33 {
    34     ios::sync_with_stdio(false); cin.tie(0);
    35 
    36     cin>>n>>m;
    37     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>maze[i][j];
    38 
    39     while(m--)
    40     {
    41         cin>>sx>>sy;
    42 
    43         //memset(vis,0,sizeof(vis));
    44         int idx=vis[sx][sy];
    45         if(idx==0)
    46         {
    47             ans=1;
    48             vis[sx][sy]=++cnt;
    49             so(sx,sy,cnt);
    50 
    51             Ans[cnt]=ans;
    52             cout<<Ans[cnt]<<endl;
    53         }
    54         else cout<<Ans[idx]<<endl;
    55     }
    56 
    57     return 0;
    58 }

    完。

  • 相关阅读:
    一本通课后练习 / 高手训练
    毒瘤 dp 题做题记录
    埃及分数
    CF340E Iahub and Permutations
    NOI2020 SDOI 爆零记
    Codeforces *1400-1600 做题记录
    Codeforces Round #636 (Div 3) 题解
    Codeforces Round #634 (Div 3) 题解
    洛谷 P4231 三步必杀
    【洛谷】【线段树+位运算】P2574 XOR的艺术
  • 原文地址:https://www.cnblogs.com/redblackk/p/9811743.html
Copyright © 2011-2022 走看看