机试笔记--搜索

一.枚举

例题一 百鸡问题

#include<bits/stdc++.h>
using namespace std;

int main(){
    int n;
    while (cin>>n) {
        for (int i = 0; i <= 100; i++) {
            for (int j = 0; j <= 100 - i; j++) {
                int m = 100 - i - j;
                if (i * 5 + 3 * j + (double) 1 / 3 * m > n)
                    break;
                else
                    cout << "x=" << i << ",y=" << j << ",z=" << m << endl;

            }
        }
    }
    return 0;
}

 例题二 老比尔 

N  _XYZ_,N是火鸡的数量,现在不知道价格的第五位和第一位,求一只火鸡的价格

有多个满足条件的价格时选择价格最高的。

假设一只火鸡的价格为整数,总价为5位数

#include <bits/stdc++.h>
using namespace std;

int main(void){
    int n, a, b, c, d, e, bcd, abcde;
    while(cin >>n >>a >>b >>c){
        bool flag = false;
        bcd = a*1000 + b*100 +c*10;
        for(int a=9; a>=1; a--){//倒着搜索,保证是最大值
            for(int e=9; e>=0; e--){
                abcde = a*10000 + bcd + e;
                if(abcde%n==0){
                    flag = true;
                    printf("%d %d %d\n", a, e, abcde/n);
                    break;
                }
            }
            if(abcde%n==0) break;
        }
        if(!flag) cout <<0 <<endl; //未找到返回0
    }
    return 0;
}

 广度优先搜索

例题:玛雅人的密码

玛雅人有一种密码,如果字符串中出现连续的2012四个数字就能解开密码。给一个长度为N的字符串,(2=<N<=13)该字符串中只含有0,1,2三种数字,问这个字符串要移位几次才能解开密码,每次只能移动相邻的两个数字。例如02120经过一次移位,可以得到20120,01220,02210,02102,其中20120符合要求,因此输出为1.如果无论移位多少次都解不开密码,输出-1。

输入:输入包含多组测试数据,每组测试数据由两行组成。

第一行为一个整数N,代表字符串的长度(2<=N<=13)。

第二行为一个仅由0、1、2组成的,长度为N的字符串。

输出:输出最少的移位次数,没有,输出-1

分析

  • 将所有可能的字符串列举出来,然后判断是否有包含“2012”的
  • 又要求输出最少的移位次数,所以应该以图的形式列举出来,然后按照广度优先搜索的方式进行遍历(因为要求的是最少的移位次数)
  • 建立这张图的方式:将源字符串作为第一个节点, 然后将它的移位字符串作为邻接点即可.
#include <bits/stdc++.h>
using namespace std;
string init;
int N;
typedef struct Node
{
    string s;
    int step;
}Node;

int bfs()
{
    Node start;
    start.s=init,start.step=0;
    queue<Node> q;
    q.push(start);
    map<string,int> m;
    m[init]=1;
    while(!q.empty()){
      Node temp=q.front();
      q.pop();
      if(temp.s.find("2012")!=temp.s.npos) return temp.step;
        for(int i=0;i<N-1;i++){
          string now = temp.s;
          char a;
          a=now[i];
          now[i]=now[i+1];
          now[i+1]=a;
          Node node;
          node.s=now,node.step=temp.step+1;
          if(m[now]==0){
            q.push(node);
            m[now]=1;
          }
        }
    }
    return -1;
}
int main()
{
    while(cin>>N>>init){
      cout << bfs() <<endl;
    }
    return 0;
}

 广度优先搜索的要点:

1.需要有一个一维或二维数组,或者是哈希表来记录是否访问过某节点

2.在while(!q.empty())中如果找到,那么就返回,一般是返回搜索的次数

3.在将周围的节点进队时要判断这个节点是否访问,未访问的话进队并且将这个节点标记

posted @ 2020-04-19 10:22  不二良  阅读(129)  评论(0编辑  收藏  举报