zoukankan      html  css  js  c++  java
  • 搜索 水题&&错误集锦

    引子:

    本以为搜索的题目老师也不会检查,结果今天早上loli慢悠悠的说:“请同学们提交一下搜索的题目~”,顿时心旌摇曳,却也只能装作镇定自若的样子,点了点头。。

    然后就开始了今天的疯狂做题,虽说题目都不是太难,但题多势众啊...

    刷了那么多题,小有收获,总结+复习一下,也是为了以后避免类似错误(十分直观而又影响巨大的)

    所做题目链接:openjudge  2.5  题面不一一附上

    1.letters

    看到这道题,就想到了前几天刚刚学会的STLmap映射,然后没怎么想就敲了一遍代码,结果跑的巨慢无比,然后下去跑操想明白了不用这么麻烦的做法,直接用一个vis数组就是了,看来长时间不做搜索大脑都僵化了。。

    其他的就没什么技术含量了,和dfs模板差不多,

    细节:1.运算种的i循环0-3就是4次

               2.起始点的vis为true

               3.A-Z ascill码为65-90

    代码:

     1 #include<iostream>
     2 #include<cstring>
     3 
     4 using namespace std;
     5 
     6 int fx[4]={0,1,0,-1};
     7 int fy[4]={-1,0,1,0};
     8 int ans=0,d[200][200],n,m;
     9 char a[25][25];bool vis[100];
    10 
    11 int dfs(int x,int y,int z)
    12 {
    13     ans=max(ans,z);
    14     for(int i=0;i<4;i++)//细节 
    15     {
    16         int xx=x+fx[i];
    17         int yy=y+fy[i];
    18         if(xx<=n&&xx>0&&yy<=m&&yy>0&&!vis[a[xx][yy]])
    19         {
    20             vis[a[xx][yy]]=true;
    21             dfs(xx,yy,z+1);
    22             vis[a[xx][yy]]=false;
    23         }
    24     }
    25 }
    26 int main()
    27 {
    28     memset(vis,false,sizeof(vis));
    29     cin>>n>>m;
    30     for(int i=1;i<=n;i++)
    31         for(int j=1;j<=m;j++)
    32             cin>>a[i][j];
    33     vis[a[1][1]]=true;//细节 
    34     dfs(1,1,1);
    35     cout<<ans<<endl;
    36     return 0;
    37 }
    letters

    2&&3.八皇后&&问题

    例题八皇后问题引申出的各种问题,比较简单,+注意细节

    细节:

          1.横纵循环的次序,外层循环行号,内层循环列号

    代码:

     1 #include<iostream>
     2 using namespace std;
     3 int s=0,n,ans[20],h[100]={0},l[100]={0},a[100]={0},b[100]={0},anss[93][20];
     4 void out()
     5 {
     6     s++;
     7     for(int i=1;i<=8;i++)
     8       anss[s][i]=ans[i];  
     9 }
    10 int dfs(int k)
    11 {
    12       //cout<<"12 ";
    13       for(int j=1;j<=8;j++)
    14         {
    15             if((h[j]==0)&&(a[k+j]==0)&&(b[k-j+8]==0))
    16             {
    17             ans[k]=j;
    18             h[j]=1;
    19             a[k+j]=1;
    20             b[k-j+8]=1;
    21             
    22             if(k==8)out();
    23               else dfs(k+1);
    24             h[j]=0;
    25             a[k+j]=0;
    26             b[k-j+8]=0;
    27             }
    28         }
    29 }
    30 int main()
    31 {
    32     dfs(1);
    33     cin>>n;
    34     for(int i=1;i<=n;i++)
    35     {
    36         int x;
    37         cin>>x;
    38         for(int k=1;k<=8;k++)
    39           cout<<anss[x][k];
    40         cout<<endl;
    41     } 
    42 }
    八皇后
     1 #include<iostream>
     2 using namespace std;
     3 int s=0,n,ans[20],h[100]={0},l[100]={0},a[100]={0},b[100]={0},anss[93][20];
     4 void out()
     5 {
     6     s++;
     7 //    if(s>4)return ;
     8     cout<<"No. "<<s<<endl;
     9     for(int i=1;i<=8;i++)
    10     {
    11       for(int j=1;j<=8;j++)
    12       {
    13           if(ans[j]==i)cout<<1<<" ";
    14           else
    15             cout<<0<<" ";
    16       }
    17       cout<<endl;
    18     }
    19 }
    20 int dfs(int k)
    21 {
    22       //cout<<"12 ";
    23       for(int j=1;j<=8;j++)
    24         {
    25             if((h[j]==0)&&(a[k+j]==0)&&(b[k-j+8]==0))
    26             {
    27             ans[k]=j;
    28             h[j]=1;
    29             a[k+j]=1;
    30             b[k-j+8]=1;
    31             
    32             if(k==8)out();
    33               else dfs(k+1);
    34             h[j]=0;
    35             a[k+j]=0;
    36             b[k-j+8]=0;
    37             }
    38         }
    39 }
    40 int main()
    41 {
    42 //    cin>>n;//cout<<"123";
    43     dfs(1);
    44     cin>>n;
    45 //    cout<<s;
    46     for(int i=1;i<=n;i++)
    47     {
    48         int x;
    49         cin>>x;
    50         for(int k=1;k<=8;k++)
    51           cout<<anss[x][k];
    52         cout<<endl;
    53     } 
    54 }
    八皇后问题

     4.迷宫

    这道题是我做openjudge交的最多的一道题,足足交了30次,自己的dfs不知道出现了什么问题,就是不对,总是5分。。。

    看了看提问区,五分的解决方法就是判断起点和终点,可是我明明判断了,无奈。。。

    唯一的细节就是题目给出的特判,所以收获也就只有好好看题。

    5.红与黑

    又是一道模板题,注意的地方就是输入的行列是反着来的,

    代码:

     1 #include <iostream>
     2 #include <cstring>
     3 using namespace std;
     4 
     5 int a[25][25];
     6 int dx[5]={0,0,1,-1},dy[5]={1,-1,0,0};
     7 int m,n,ans=0,xe,ye;
     8 
     9 void dfs(int x,int y)
    10 {
    11     ans++;
    12     a[x][y]=0;
    13     for(int i=0;i<=3;i++)
    14     {
    15         int xx=x+dx[i];
    16         int yy=y+dy[i];
    17         if(xx<=m&&xx>0&&yy<=n&&yy>0&&a[xx][yy]==1)
    18         {
    19             a[xx][yy]=0;
    20             dfs(xx,yy);
    21         }
    22     }
    23 }
    24 
    25 int main()
    26 {
    27     while(cin>>n>>m)
    28     {
    29         memset(a,0,sizeof(a));
    30         ans=0;
    31         if(m==0&&n==0)break;
    32         for(int i=1;i<=m;i++)
    33           for(int j=1;j<=n;j++)
    34            {
    35             char x;
    36             cin>>x;
    37             if(x=='.')
    38               a[i][j]=1;
    39             if(x=='@')
    40             {
    41               a[i][j]=1;
    42               xe=i,ye=j;
    43             }
    44         }
    45         dfs(xe,ye);
    46         cout<<ans<<endl;
    47     }
    48     return 0;
    49 }
    红与黑

    6.棋盘问题

    这道题第一次交的时候WA0分,主要是因为没好好看题,'#' 的地方才可以放棋子,可是受了上一道题的影响,+盲目自信没试样例2导致了如此惨剧的发生

    收获:好好看题X2!!

    7.取石子游戏

    这明明就是递归,不知道为什么放到搜索上来= =

    注意每次是谁先手,这里num=1为player1放棋子,player1设为先手拿旗子,

    用3目运算符小装了一手,感觉良好,

    这道题写了两遍,主要注意取到0获胜的到底是递归上一层的player还是这一层的player,总归最后还是理清了思路。

    代码:

     1 #include <iostream>
     2 #include <cmath>
     3 #include <cstdio>
     4 #include <algorithm>
     5 
     6 using namespace std;
     7 int f(long long  a,long long  b,int num)
     8 {
     9     if(a<b)swap(a,b);
    10     if(b==0)return num==1?2:1;
    11     if(a/b>=2)return num;
    12     a-=b;
    13     return f(a,b,num==1?2:1);
    14 }
    15 int main()
    16 {
    17     long long  a,b;
    18     while(cin>>a>>b)
    19     {
    20         if(a==0&&b==0)break;
    21         if(f(a,b,1)==1)
    22           cout<<"win"<<endl;
    23         else
    24           cout<<"lose"<<endl;
    25     }
    26 }
    取石子游戏(递归)

    8.马走日

    和dfs模板略有不同的特点可能是八个方向吧,每次走到ans++就好,一次AC

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 
     5 using namespace std;
     6 
     7 int m,n,ans;
     8 int dx[10]={1,1,2,2,-1,-1,-2,-2},dy[10]={2,-2,1,-1,2,-2,1,-1};
     9 int vis[15][15];
    10 void dfs(int x,int y,int s)
    11 {
    12     if(s>n*m)
    13     {
    14         ans++;
    15         return;
    16     }
    17     for(int i=0;i<8;i++)
    18     {
    19         int xx=x+dx[i];
    20         int yy=y+dy[i];
    21         if(xx>=0&&xx<=n-1&&yy>=0&&yy<=m-1)
    22         if(!vis[xx][yy])
    23         {
    24             vis[xx][yy]=1;
    25             dfs(xx,yy,s+1);
    26             vis[xx][yy]=0;
    27         }
    28     }
    29 }
    30 int main()
    31 {
    32     int u,a,b;
    33     cin>>u;
    34     while(u--)
    35     {
    36         memset(vis,0,sizeof(vis));
    37         cin>>n>>m>>a>>b;
    38         ans=0;
    39         vis[a][b]=1;
    40         dfs(a,b,2);
    41         cout<<ans<<endl;
    42     }
    43 }
    马走日

    9.单词接龙

    记得当时刚来集训,和Juan_feng一起讨论后A掉了这道题(多亏我机智的+1,虽然不知道原理),高兴了一手,

    不过听loli讲我们这样做的效率很低,直接把能不能连接,连接后长度增加多少,先预处理出一个二维数组就可以,不用每次都搜索,效率会快很多,深思熟虑后确实是这样,不过代码是之前的版本,有点小懒

    代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 
     5 using namespace std;
     6 
     7 int m,n,ans;
     8 int dx[10]={1,1,2,2,-1,-1,-2,-2},dy[10]={2,-2,1,-1,2,-2,1,-1};
     9 int vis[15][15];
    10 void dfs(int x,int y,int s)
    11 {
    12     if(s>n*m)
    13     {
    14         ans++;
    15         return;
    16     }
    17     for(int i=0;i<8;i++)
    18     {
    19         int xx=x+dx[i];
    20         int yy=y+dy[i];
    21         if(xx>=0&&xx<=n-1&&yy>=0&&yy<=m-1)
    22         if(!vis[xx][yy])
    23         {
    24             vis[xx][yy]=1;
    25             dfs(xx,yy,s+1);
    26             vis[xx][yy]=0;
    27         }
    28     }
    29 }
    30 int main()
    31 {
    32     int u,a,b;
    33     cin>>u;
    34     while(u--)
    35     {
    36         memset(vis,0,sizeof(vis));
    37         cin>>n>>m>>a>>b;
    38         ans=0;
    39         vis[a][b]=1;
    40         dfs(a,b,2);
    41         cout<<ans<<endl;
    42     }
    43 }
    单词接龙

    10.分成互质组

    一遍ac,小开心一手,

    dfs每个数是加入之前的已经建立的组别 or 新开一个组

    搜完统计一下组数就是了,

    然后还有个剪枝:如果当前组别已经大于目前最优解就return,因为不可能对答案有贡献了,

    这道题很怪异的是,我居然自己能把自己的错误卡掉,虽然效率低了一点。。

    本来就打算拿部分分的,毕竟从来没有错误再卡掉的操作,结果ac了,有点开心

    代码:

     1 #include <iostream>
     2 #define re register
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 int n,a[15],vis[15],ans=15,tot[15],z[15][15];
     7 
     8 int gcd(int x,int y)
     9 {
    10     if(y==0)return x;
    11     else
    12       return gcd(y,x%y);
    13 }
    14 
    15 void dfs(int k,int s)
    16 {
    17     if(s>=ans)return ;
    18     if(k>n)
    19     {
    20         int pd=0;
    21         for(int i=0;i<=s;i++)
    22           pd+=tot[i];
    23         if(pd!=n)return;//卡掉自己不知道为什么会出现的错误 
    24         ans=min(ans,s+1);
    25         return ;
    26     }
    27     for(re int i=0;i<=s;i++)
    28     {
    29         bool flag=true;
    30         for(int l=1;l<=tot[i];l++)
    31         {
    32             if(gcd(z[i][l],a[k])!=1)
    33             {
    34                 flag=false;
    35                 break;
    36             }
    37         }
    38         if(flag)
    39         {
    40             tot[i]++;
    41             z[i][tot[i]]=a[k];
    42             dfs(k+1,s);
    43             tot[i]--;
    44         }
    45     }
    46     s++;
    47 //    cout<<s;
    48     z[s][1]=a[k];
    49     tot[s]=1;
    50     dfs(k+1,s);
    51     s--;
    52     tot[s]=0;
    53 }
    54 
    55 int main()
    56 {
    57     cin>>n;
    58     for(int i=1;i<=n;i++)
    59       cin>>a[i];
    60     dfs(1,0);
    61 //    cout<<"daole";
    62     cout<<ans;
    63 }
    分成互质组

    11.分苹果

    又是一道递归题,,

    在OJ的递归和递推都有这道题,思维难度还是有的

    代码:

     1 #include<iostream>
     2 using namespace std;
     3 int put(int x,int y)
     4 {
     5     if((x==1)||(y==1)||(y==0))
     6       return 1;
     7     if(x<y)
     8       return put(x,x); 
     9     if(x==y)
    10       return put(x,y-1)+1;
    11     if(x>y)
    12       return put(x,y-1)+put(x-y,y);
    13 }
    14 main()
    15 {
    16     int n,x,y;
    17     cin>>n;
    18     
    19     for (int i=1;i<=n;i++)
    20     {
    21         cin>>x>>y;
    22         cout<<put(x,y)<<endl;
    23     }
    24     return 0;
    25 }
    放苹果

    啊终于写完了,

    dfsOJ搜索水题的总结如上

    ———————————————————————————————— 执笔饰年华,一笑叹天涯。逢春即润物,生当得潇洒。
  • 相关阅读:
    九、linux-msyql下的mysql主从复制深度实战
    八、linux-mysql的mysql主从复制原理和实战
    七、linux-mysql下mysql增量备份与恢复
    六、linux-mysql的mysql字符集问题
    入坑django2
    python根据已有数据库生成model.py
    docker 常用命令记录
    gitlab自带的Nginx与原Nginx冲突的解决方案
    linux下PHP安装redis扩展
    jenkins自动部署代码到多台服务器
  • 原文地址:https://www.cnblogs.com/SuperGoodGame/p/9079748.html
Copyright © 2011-2022 走看看