码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-06-16 00:36:18      阅读:147      评论:0      收藏:0      [点我收藏+]

标签:code   center   出队   数据量   坐标   简单   search   push   bre   

枚举:

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

例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

 

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

标签:code   center   出队   数据量   坐标   简单   search   push   bre   

原文地址:https://www.cnblogs.com/yun-an/p/11029331.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!