• 最基础的“穷竭搜索”



     栈(Stack)

     1 #include <stack>
     2 #include <cstdio>
     3  
     4 using namespace std;
     5 
     6 int main(int argc, char * argv[])
     7 {
     8     stack<int> s;
     9     s.push(1);
    10     s.push(2);
    11     s.push(3);
    12     printf("%d
    ",s.size());
    13     printf("%d
    ",s.empty()); 
    14     printf("%d
    ",s.top());
    15     s.pop();
    16     printf("%d
    ",s.top());
    17     s.pop();
    18     printf("%d
    ",s.top());//stack非空 
    19     s.pop();
    20     printf("%d
    ",s.size());
    21     printf("%d
    ",s.empty()); 
    22     return 0; 
    23 } 

    队列(Queue)

     1 #include <queue>
     2 #include <cstdio>
     3 
     4 using namespace std;
     5 
     6 int main(int argc, char * argv[])
     7 {
     8     queue<int> que;
     9     que.push(1);
    10     que.push(2);
    11     que.push(3);
    12     printf("%d
    ",que.size());
    13     printf("%d
    ",que.front());
    14     printf("%d
    ",que.back());
    15     que.pop();
    16     printf("%d
    ",que.size());
    17     printf("%d
    ",que.front());
    18     printf("%d
    ",que.back());
    19     que.pop();
    20     printf("%d
    ",que.size());
    21     printf("%d
    ",que.front());
    22     printf("%d
    ",que.back());
    23     que.pop();
    24     printf("%d
    ",que.size());
    25     printf("%d
    ",que.front());//队列为空,返回值是不确定的
    26     printf("%d
    ",que.back());//队列为空,返回值是不确定的 
    27     printf("%d
    ",que.empty());
    28 } 

    部分和问题

    • 题目大意:给定整数a1,a2,…,an,判断是否可以从中选出若干数,使它们的和恰好为k
    • 限制条件:
      • 1≤n≤20
      • -108≤ai≤108
      • -108≤k≤108
    • 题解:深度优先搜索,从a1开始按顺序决定每个数加或不加,在全部n个数都决定后在判断它们的和是不是k即可。因为状态数是2n,所以复杂度是O(2n)。
    • 代码:
       1 #include <iostream>
       2 
       3 using namespace std;
       4 
       5 bool dfs(int, int);
       6 
       7 int n,k;
       8 int * a;
       9 
      10 int main()
      11 {
      12     cin >> n >> k;
      13     a = new int[n];
      14     for (int i=0; i<n; i++)
      15     {
      16         cin >> a[i];
      17     }
      18     bool f=dfs(0,0);
      19     if (f) cout << "Yes!
      ";
      20     else cout << "No!
      "; 
      21 }
      22 
      23 bool dfs(int i, int s)//已经从前n项得到了和s
      24 {
      25     if (i==n) return s==k;//如果前n项都已经计算过了,返回s与k是否相等 
      26     if (dfs(i+1,s)) return true;// 不加上a[i]的情况 
      27     if (dfs(i+1,s+a[i])) return true;//加上a[i]的情况 
      28     return false;//无论是否加上a[i]都不能凑成k就返回false 
      29 }
      部分和问题

    Lake Counting(POJ 2386)

    • 原题如下:
      Lake Counting
      Time Limit: 1000MS Memory Limit: 65536K
      Total Submissions: 44746 Accepted: 22116

      Description

      Due to recent rains, water has pooled in various places in Farmer John's field, which is represented by a rectangle of N x M (1 <= N <= 100; 1 <= M <= 100) squares. Each square contains either water ('W') or dry land ('.'). Farmer John would like to figure out how many ponds have formed in his field. A pond is a connected set of squares with water in them, where a square is considered adjacent to all eight of its neighbors. 

      Given a diagram of Farmer John's field, determine how many ponds he has.

      Input

      * Line 1: Two space-separated integers: N and M 

      * Lines 2..N+1: M characters per line representing one row of Farmer John's field. Each character is either 'W' or '.'. The characters do not have spaces between them.

      Output

      * Line 1: The number of ponds in Farmer John's field.

      Sample Input

      10 12
      W........WW.
      .WWW.....WWW
      ....WW...WW.
      .........WW.
      .........W..
      ..W......W..
      .W.W.....WW.
      W.W.W.....W.
      .W.W......W.
      ..W.......W.

      Sample Output

      3

      Hint

      OUTPUT DETAILS: 

      There are three ponds: one in the upper left, one in the lower left,and one along the right side.
    • 题解:从任意的'W'开始,不停地把邻接的部分用'.'代替,1次dfs后与初始的这个W连接的所有'W'就都被替换成了'.',因此直到图中不再存在w为止,总共进行dfs的次数就是答案了,复杂度是O(8*n*m)=O(m*n)
    • 代码:
       1 #include <iostream>
       2 
       3 using namespace std;
       4 
       5 int n,m;
       6 char ** a;
       7 
       8 void dfs(int, int);
       9 
      10 int main()
      11 {
      12     cin >> n >> m;
      13     a = new char*[n];
      14     for (int i=0; i<n; i++) a[i]=new char[m];
      15     for (int i=0; i<n; i++)
      16     {
      17         for (int j=0; j<m; j++)
      18         {
      19             cin >> j[i[a]];
      20         }
      21     }
      22     int s=0;
      23     for (int i=0; i<n; i++)
      24     {
      25         for (int j=0; j<m; j++)
      26         {
      27             if (j[i[a]]=='W') 
      28             {
      29                 dfs(i,j);
      30                 ++s;
      31             }
      32         }
      33     }
      34     cout << s << endl;
      35 }
      36 
      37 void dfs(int x, int y)
      38 {
      39     y[x[a]] ='.';
      40     for (int dx=-1; dx<=1; dx++)
      41     {
      42         for (int dy=-1; dy<=1; dy++)
      43         {
      44             int xx=x+dx, yy=y+dy;
      45             if (xx>=0 && xx<n && yy>=0 && yy<m && yy[xx[a]]=='W') dfs(xx,yy);
      46         }
      47     }
      48 }
      Lake Counting

     迷宫的最短路径

    • 题目大意:给定一个大小为N*M的迷宫,迷宫由通道和墙壁组成,每一步可以向邻接的上下左右四格的通道移动,要求出从起点到终点所需的最小步数。假定从起点一定可以移动到终点。
    • 限制条件:N,M≤100
    • 题解:宽度优先搜索按照距开始状态由近及远的顺序进行搜索(只要将已经访问的状态用标记管理起来),因此可以很容易地用来求最短路径、最少操作之类问题的答案。这个问题中状态仅仅是目前所在位置的坐标,因此可以构造成pair或者编码成int来表达状态。当状态更加复杂时,就需要封装成一个类来表示状态了。复杂度是O(4*n*m)=O(n*m)
    • 代码:
       1 #include <iostream>
       2 #include <queue>
       3 using namespace std;
       4 typedef pair<int,int> P;
       5 
       6 const int INF=100000000;
       7 const int MAX_N=100;
       8 const int MAX_M=100;
       9 char maze[MAX_N][MAX_M+1];
      10 int n,m;
      11 int sx=0,sy=1;
      12 int tx=9,ty=8;
      13 const int dx[4]{-1,0,0,1};
      14 const int dy[4]{0,1,-1,0};
      15 int d[MAX_N][MAX_M];
      16 
      17 int bfs();
      18 
      19 int main()
      20 {
      21     cin >> n >> m;
      22     for (int i=0; i<n; i++)
      23         for (int j=0; j<m; j++)
      24             cin >> j[i[maze]];
      25     cout << bfs();
      26 }
      27 
      28 int bfs()
      29 {
      30     queue<P> que;
      31     for (int i=0; i<n; i++)
      32         for (int j=0; j<n; j++)
      33             j[i[d]]=INF;
      34     que.push(P(sx,sy));
      35     sy[sx[d]]=0;
      36     while (que.size())
      37     {
      38         P p=que.front();
      39         que.pop();
      40         if (p.first==tx && p.second==ty) break;
      41         for (int i=0; i<4; i++)
      42         {
      43             int xx=p.first+dx[i];
      44             int yy=p.second+dy[i];
      45             if (xx>=0 && xx<n && yy>=0 && yy<m && yy[xx[maze]]!='#' && yy[xx[d]]==INF)
      46             {
      47                 que.push(P(xx,yy));
      48                 yy[xx[d]]=p.second[p.first[d]]+1;
      49             }
      50         }
      51     }
      52     return ty[tx[d]];
      53 }
      迷宫的最短路径

     特殊状态的枚举

    虽然生成可行解空间多数采用深度优先搜索,但在状态空间比较特殊时其实可以很简短地实现

    如,C++标准库中提供了next_permutation函数,可以把n个元素共n!种不同的排列生成出来

    又如,通过位运算,可以枚举n个元素中取出k个的共C(n,k)种状态或是某个集合中的全部子集等

    贴一段书上的代码:

     1 bool used[MAX_N];
     2 int perm[MAX_N];
     3 
     4 void permutation1(int pos, int n)
     5 {
     6     if (pos==n)
     7     {
     8         /*
     9          *这里编写需要对perm进行的操作 
    10          */
    11         return ; 
    12     }
    13     for (int i=0; i<n; i++)
    14         if (!used[i])
    15         {
    16             perm[pos]=i;
    17             used[i]=true;
    18             permutation1(pos+1,n);
    19             used[i]=false;
    20         }
    21     return ;
    22 }
    23 _______________________________________________
    24 #include <algorithm>
    25 //即使有重复的元素也会生成所有的排列
    26 //next_permutation是按照字典序来生成下一个排列的
    27 int perm2[MAX_N];
    28 void permutation2(int n)
    29 {
    30     for (int i; i<n; i++) perm2[i]=i;
    31     do
    32     {
    33         /*
    34          *这里编写需要对perm2进行的操作 
    35          */
    36     }
    37     while (next_permutation(perm2, perm+n));
    38     //所有的排列都生成后,next_permutation会返回false 
    39     return ;
    40 }
  • 相关阅读:
    IE8中li添加float属性,中英数字混合BUG
    jQuery ajax get与post后台交互中的奥秘
    BZOJ 4816 数字表格
    BZOJ 1598 牛跑步
    BZOJ 4077 Messenger
    相关分析 BZOJ 4821
    Crash的数字表格 BZOJ 2154 / jzptab BZOJ 2693
    回文串 BZOJ 3676
    古代猪文 BZOJ 1951
    树上的路径 BZOJ 3784
  • 原文地址:https://www.cnblogs.com/Ymir-TaoMee/p/9404341.html
Copyright © 2020-2023  润新知