标签: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; }
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; }
标签:code center 出队 数据量 坐标 简单 search push bre
原文地址:https://www.cnblogs.com/yun-an/p/11029331.html