习题6-12 筛子难题 UVa810

来源:互联网 发布:linux如何关闭echo 编辑:程序博客网 时间:2024/04/30 06:30

1.题目描述:点击打开链接

2.解题思路:本题是迷宫问题,典型的BFS解法。不过首先应当确定状态是什么。根据题意描述:筛子的坐标+筛子的前面和顶面即构成了一个状态。这样以来,其实本题有点类似于隐式图的搜索。那么状态是怎么逐步扩展的呢?由于筛子每次都有四个方向可以滚动,因此通过判断滚动后的新状态是否合法即可扩展开来。不过向左,向右滚动需要提前打表,列出24种顶面是u,正面是f的右侧面值。详细部分见代码注释。

3.代码:

#define _CRT_SECURE_NO_WARNINGS #include<iostream>#include<algorithm>#include<string>#include<sstream>#include<set>#include<vector>#include<stack>#include<map>#include<queue>#include<deque>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<functional>using namespace std;const int D[4][2] = { -1, 0, 1, 0, 0, -1, 0, 1 };const int N = 15;char str[25];int n, m, sx, sy, u, f, g[N][N];int vis[N][N][7][7];int to[7][7];struct State{int x, y, u, f;//坐标,顶面,正面int pre;//父结点编号State(){}State(int x, int y, int u, int f, int pre){this->x = x;this->y = y;this->u = u;this->f = f;this->pre = pre;}}q[10005];void tra(int&vu, int&vf, int d){if (d == 0){ int tmp = vf; vf = 7 - vu; vu = tmp; }//向上if (d == 1){ int tmp = vu; vu = 7 - vf; vf = tmp; }//向下if (d == 2)vu = 7 - to[vu][vf];//向右if (d == 3)vu = to[vu][vf];//向左}typedef pair<int, int>P;vector<P>ans;void print(int u)//递归寻找根结点,好处是入队列顺序正好是顺序的,不过只适用于路径较短的情况{if (u == -1)return;print(q[u].pre);ans.push_back(P(q[u].x, q[u].y));}void bfs(){ans.clear();int head = 0, rear = 0;q[rear++] = State(sx, sy, u, f, -1);memset(vis, 0, sizeof(vis));vis[sx][sy][u][f] = 1;while (head < rear){State u = q[head++];//出队列for (int i = 0; i < 4; i++){State v = u;v.x += D[i][0], v.y += D[i][1];if (v.x <= 0 || v.x>n || v.y <= 0 || v.y>m)continue;if (g[v.x][v.y] != -1 && u.u != g[v.x][v.y])continue;if (v.x == sx&&v.y == sy){print(head - 1);//沿着父结点找到根ans.push_back(P(sx, sy));//由于int tot = ans.size();for (int i = 0; i < tot; i++){if (i % 9 == 0)printf("\n  ");printf("(%d,%d)%c", ans[i].first, ans[i].second, i == tot - 1 ? '\n' : ',');}return;}tra(v.u, v.f, i);if (vis[v.x][v.y][v.u][v.f])continue;vis[v.x][v.y][v.u][v.f] = 1;//标记访问过v.pre = head - 1;//记录父结点编号q[rear++] = v;//入队列}}printf("\n  No Solution Possible\n");}int main(){//freopen("t.txt", "r", stdin);to[1][2] = 4; to[1][3] = 2; to[1][4] = 5; to[1][5] = 3;//打表,to[u][f]表示顶面是u,正面是f时的右侧面的值to[2][1] = 3; to[2][3] = 6; to[2][4] = 1; to[2][6] = 4;to[3][1] = 5; to[3][2] = 1; to[3][5] = 6; to[3][6] = 2;to[4][1] = 2; to[4][2] = 6; to[4][5] = 1; to[4][6] = 5;to[5][1] = 4; to[5][3] = 1; to[5][4] = 6; to[5][6] = 3;to[6][2] = 3; to[6][3] = 5; to[6][4] = 2; to[6][5] = 4;while (~scanf("%s", str) && strcmp(str, "END")){printf("%s", str);scanf("%d%d%d%d%d%d", &n, &m, &sx, &sy, &u, &f);for (int i = 1; i <= n;i++)for (int j = 1; j <= m; j++)scanf("%d", &g[i][j]);bfs();}return 0;}

0 0
原创粉丝点击