机试指南第六章-搜索-例题自解

Posted yun-an

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了机试指南第六章-搜索-例题自解相关的知识,希望对你有一定的参考价值。

枚举:

枚举是最简单也是最直白的搜索方式,它依次尝试搜索空间中所有的解,测试其是否符合条件,若符合则输出答案,否则继续测试下一组解。

例6.1 百鸡问题

#include<iostream>
using namespace std;

int main()

    int n;
    while (cin >> n) 
    
        for (int x = 0; x <= 100; x++)
        
            for (int y = 0; y <= 100 - x; y++)
            
                int z = 100 - x - y;
                if (x * 5 * 3 + y * 3 * 3 + z <= n * 3)
                
                    cout << "x=" << x << ",y=" << y << ",z=" << z << endl;
                
            
        
    
    return 0;

广度优先搜索(BFS:breadth-first search):

 例6.2 胜利大逃亡(广搜+剪枝)

AC代码:

技术图片
#include<cstdio>
#include<queue>
using namespace std;

bool mark[50][50][50];//标记数组,用来确保每个结点只被访问一次
int maze[50][50][50];//保存立方体的信息
struct N //状态结构体

    int x, y, z; //结点坐标
    int t;//达到该结点的最短时间
;

queue<N> Q;//队列符合操作顺序,先读入起点,也先从起点开始遍历
int go[][3] =  1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1 ;//六个方向

int BFS(int a, int b, int c)//广搜,返回最少耗时

    while (Q.empty() == false)//当队列中仍有元素可以拓展时,继续循环
    
        N now = Q.front();//得到队头的状态
        Q.pop();//从队列中弹出队头的状态
        for (int i = 0; i < 6; i++)//依次拓展相应的六个结点
        
            int nx = now.x + go[i][0];
            int ny = now.y + go[i][1];
            int nz = now.z + go[i][2];//计算新坐标
            if (nx < 0 || nx >= a || ny < 0 || ny >= b || nz < 0 || nz >= c)continue;//新坐标在立方体之外则丢弃该坐标
            if (maze[nx][ny][nz] == 1)continue;//该坐标为墙,丢弃
            if (mark[nx][ny][nz] == true)continue;//该坐标已被访问,丢弃
            N tmp;//新的状态
            tmp.x = nx;
            tmp.y = ny;
            tmp.z = nz;//新状态坐标
            tmp.t = now.t + 1;//新状态的耗时
            Q.push(tmp);//将新状态加入队列
            mark[nx][ny][nz] = true;
            if (nx == a - 1 && ny == b - 1 && nz == c - 1)return tmp.t;//该坐标为终点,直接返回其耗时
        
    
    return -1;//所有状态查找完之后仍然找不到所需坐标,返回-1


int main()

    int T;
    scanf("%d", &T);
    while (T--)
    
        int a, b, c, t;
        scanf("%d%d%d%d", &a, &b, &c, &t);
        for (int i = 0; i < a; i++)
        
            for (int j = 0; j < b; j++)
            
                for (int k = 0; k < c; k++)
                
                    scanf("%d", &maze[i][j][k]);
                    mark[i][j][k] = false;
                
            
        
        while (Q.empty() == false) Q.pop();//清空上一个队列
        mark[0][0][0] = true;//标记起点
        N tmp;
        tmp.t = tmp.x = tmp.y = tmp.z = 0;
        Q.push(tmp);//将初始状态放入队列
        int ans = BFS(a, b, c);//广搜开始启动
        if (ans <= t)printf("%d\n", ans); //小于等于时间要求,输出
        else  printf("-1\n");
    
    return 0;
View Code

TLE代码(使用cin超时了,数据量过大,scanf更快)

技术图片
#include<iostream>
#include<queue>
using namespace std;

bool mark[50][50][50];//标记数组,用来确保每个结点只被访问一次
int maze[50][50][50];//保存立方体的信息
struct N //状态结构体

    int x, y, z; //结点坐标
    int t;//达到该结点的最短时间
;

queue<N> Q;//队列符合操作顺序,先读入起点,也先从起点开始遍历
int go[][3] =  1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1 ;//六个方向

int BFS(int a, int b, int c)//广搜,返回最少耗时

    while (Q.empty() == false)//当队列中仍有元素可以拓展时,继续循环
    
        N now = Q.front();//得到队头的状态
        Q.pop();//从队列中弹出队头的状态
        for (int i = 0; i < 6; i++)//依次拓展相应的六个结点
        
            int nx = now.x + go[i][0];
            int ny = now.y + go[i][1];
            int nz = now.z + go[i][2];//计算新坐标
            if (nx < 0 || nx >= a || ny < 0 || ny >= b || nz < 0 || nz >= c)continue;//新坐标在立方体之外则丢弃该坐标
            if (maze[nx][ny][nz] == 1)continue;//该坐标为墙,丢弃
            if (mark[nx][ny][nz] == true)continue;//该坐标已被访问,丢弃
            N tmp;//新的状态
            tmp.x = nx;
            tmp.y = ny;
            tmp.z = nz;//新状态坐标
            tmp.t = now.t + 1;//新状态的耗时
            Q.push(tmp);//将新状态加入队列
            mark[nx][ny][nz] = true;
            if (nx == a - 1 && ny == b - 1 && nz == c - 1)return tmp.t;//该坐标为终点,直接返回其耗时
        
    
    return -1;//所有状态查找完之后仍然找不到所需坐标,返回-1


int main()

    int T;
    cin >> T;
    while (T--)
    
        int a, b, c, t;
        cin >> a >> b >> c >> t;
        for (int i = 0; i < a; i++)
        
            for (int j = 0; j < b; j++)
            
                for (int k = 0; k < c; k++)
                
                    cin >> maze[i][j][k];
                    mark[i][j][k] = false;
                
            
        
        while (Q.empty() == false) Q.pop();//清空上一个队列
        mark[0][0][0] = true;//标记起点
        N tmp;
        tmp.t = tmp.x = tmp.y = tmp.z = 0;
        Q.push(tmp);//将初始状态放入队列
        int ans = BFS(a, b, c);//广搜开始启动
        if (ans <= t)cout << ans << endl;//小于等于时间要求,输出
        else cout << -1 << endl;
    
    return 0;
View Code

 

以上是关于机试指南第六章-搜索-例题自解的主要内容,如果未能解决你的问题,请参考以下文章

机试指南第二章-经典入门-Hash的应用自解

第六章例题

第六章部分例题

第六章部分例题

第六章部分例题

第六章部分例题