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