UVa #810 A Dicey Problem (习题6-12)
来源:互联网 发布:mssql 分页sql语句 编辑:程序博客网 时间:2024/04/30 02:24
(原题:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=10&page=show_problem&problem=751 )
感觉这道题和例题6-14 Abott's Revenge很像,都是在图的bfs求最短路的基础上增加了一个维度。在Abott's Revenge中,增加的维度是前进的方向,而这道题增加的维度则是色子的形态。
我把色子的六个面按照如下的顺序编号(图片借用了UVa#253 习题4-4 Cube Paiting),然后用一个int数组保存。例如当前的色子表示为1 2 3 4 5 6,向右旋转后则变为3 2 6 1 5 4。
其他的地方则是普通的bfs,中间需要注意一些细节:
1、maze坐标是从1开始
2、色子旋转的函数要测试正确性
3、色子最初形态的初始化的方法
4、判断当前状态是否曾经访问过的方法
一开始给色子初始化的时候伤了脑筋,中间的很多细节问题也导致了较长时间的debug。。不过很开心一次就AC了
还有内存泄露的问题没有解决,另外不太清楚如果不用指针的话应该怎么做
Run Time: 0.026s
// UVa #6-12.810.cpp#include<iostream>#include<stack>#include<vector>#include<queue>#include<cstring>#include<cstdlib>#include<cstdio>using namespace std;#define maxn 20struct State { //色子的状态,包括色子的位置和形态 int r, c; int dice[6]; State* father; //bfs最短路父节点 State(int x, int y) { r = x; c = y; for(int i = 0; i < 6; i ++) dice[i] = i+1; father = NULL; } State(int x, int y, int* a) { r = x; c = y; for(int i = 0; i < 6; i ++) dice[i] = a[i]; father = NULL; }};//Global Variableint step[2][4] = {{-1,0,1,0},{0,1,0,-1}}; //step用于走路。step[0]对应行的变化,step[1]对应列的变化。0为向上,之后1,2,3按顺时针顺序int m, n, startR, startC, startTop, startFront;int maze[maxn][maxn];/////void swap(State* s, int a, int b);void rot(State* s, int d); //旋转色子void initiate(State* s); //将色子置为题目给出的形态int inside(int x, int y); //判断是否在maze内int statecmp(State* s1, State* s2); //比较两个状态是否相同(也可重载State的==操作符)State* solve(State* startS); //主逻辑,bfsvoid print_ans(State* endS); //打印解int main() { char name[50]; while(scanf("%s", name) && strcmp(name, "END")) { scanf("%d%d%d%d%d%d", &m, &n, &startR, &startC, &startTop, &startFront); memset(maze, 0, sizeof(maze)); for(int i = 1; i <= m; i ++) for(int j = 1; j <= n; j ++) scanf("%d", &maze[i][j]);// if(startTop + startFront == 7) {// printf("%s\n No Solution Possible\n", name); //如果题目给出了一种不可能出现的dice config,这里可以直接判否。但是本题不用这个判断也可以AC// continue;// } State* startS = new State(startR, startC); initiate(startS); printf("%s\n", name); print_ans(solve(startS)); //这里有内存泄露,可以用内存池来解决。 } return 0;}void rot(State* s, int d) { switch(d) { case 0: swap(s, 0, 1); swap(s, 4, 5); swap(s, 1, 4); break; case 1: swap(s, 0, 2); swap(s, 3, 5); swap(s, 0, 5); break; case 2: swap(s, 1, 4); swap(s, 0, 1); swap(s, 4, 5); break; case 3: swap(s, 0, 2); swap(s, 3, 5); swap(s, 2, 3); break; case 4: swap(s, 1, 2); swap(s, 3, 4); swap(s, 1, 4); break; }}void initiate(State* s) { for(int i = 0; i < 4; i ++) { if(s->dice[0] == startTop) break; rot(s, 0); } for(int i = 0; i < 4; i ++) { if(s->dice[0] == startTop) break; rot(s, 1); } //上面分别按x轴和y轴旋转,直到达到题目要求的top面 for(int i = 0; i < 4; i ++) { if(s->dice[1] == startFront) break; rot(s,4); } //按z轴旋转,直到达到题目要求的冲着自己的(front)面}void swap(State* s, int a, int b) { int tmp = s->dice[a]; s->dice[a] = s->dice[b]; s->dice[b] = tmp;}int inside(int x, int y) { if(x < 1 || x > m || y < 1 || y > n) return 0; return 1;}int statecmp(State* s1, State* s2) { if(s1->r != s2->r || s1->c != s2->c) return 0; for(int i = 0; i < 6; i ++) if((s1->dice)[i] != (s2->dice)[i]) return 0; return 1;}State* solve(State* startS) { //BFS vector<State*> vis; queue<State*> q; q.push(startS); int moveflag = 0; //避免一开始就判断为抵达 while(!q.empty()) { State* curS = q.front(); q.pop(); int curR = curS->r, curC = curS->c; if(curR == startR && curC == startC && moveflag) return curS; //抵达目的地 int flag = 0; for(int i = 0; i < vis.size(); i ++) if(statecmp(vis[i], curS)) { flag = 1; break; } if(flag) continue; //若之前到达过这个状态则不往下继续。这里用map会比较快,但是要定义State的小于号操作符。鉴于状态的可能性不算多(10^2级),这里就不做优化了 vis.push_back(curS); for(int i = 0; i < 4; i ++) { int newR = curR + step[0][i], newC = curC + step[1][i]; if(inside(newR, newC) && (maze[newR][newC] == curS->dice[0] || maze[newR][newC] == -1)) { State* newS = new State(newR, newC, curS->dice); //再次:这里应该用内存池解决泄露 rot(newS, i); newS->father = curS; q.push(newS); moveflag = 1; } } } return NULL;}void print_ans(State* endS) { if(endS == NULL) { printf(" No Solution Possible\n"); return; } State* curS = endS; stack<pair<int,int> > s; while(curS != NULL) { s.push(pair<int,int>(curS->r, curS->c)); curS = curS->father; } int cnt = 0; printf(" "); while(1) { printf("(%d,%d)", s.top().first, s.top().second); s.pop(); if(!s.empty()){ printf(","); if((++cnt)%9 == 0) { printf("\n"); printf(" "); } } else { printf("\n"); break; } }}
0 0
- UVa #810 A Dicey Problem (习题6-12)
- UVa 810 - A Dicey Problem
- UVA 810 - A Dicey Problem
- Uva - 810 - A Dicey Problem
- A Dicey Problem UVA
- A Dicey Problem UVA
- UVA 810 - A Dicey Problem(BFS)
- uva 810 - A Dicey Problem(隐式图)
- 810 - A Dicey Problem
- 习题6-12 筛子难题(A Dicey Problem, ACM/ICPC World Finals 1999, UVa810)
- A Dicey Problem (Uva 810 & poj 1872 bfs)
- UVa810 - A Dicey Problem
- UVa 810 - A Dicey Problem(BFS+记录状态判重)
- POJ 1872 A Dicey Problem
- poj 1872 A Dicey Problem (bfs+WordFinal题)
- poj 1872 A Dicey Problem (bfs 四维判重 )
- poj1872A Dicey Problem
- poj 1872 A Dicey Problem WA的代码,望各位指教!!!
- Linux下安装maven-及常用命令
- 使用GSON解析复杂的JSON数据(有DEMO)
- android屏幕横向滚动,android图片横向滚动
- ehcache memcache redis 三大缓存男高音
- JPA基本属性注解
- UVa #810 A Dicey Problem (习题6-12)
- expdp排除特定用户的特定表
- linux下挂载img方法
- 第十四周项目六读程序(3)
- 掌握vs2010调试,入门指南
- 老妈在饭店吃饭
- APK动态加载框架(DL)解析
- Django开发环境搭建
- kernel panic 调试方法(1)