链接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1325

题意:

从迷宫的S处出发,每次可以往东、南、西、北4个方向之一前进。如果前方有墙壁,游戏者可以把墙壁往前推一格。
如果有两堵或者多堵连续的墙,则不能推动。另外,游戏者也不能推动游戏区域边界上的墙。
用最少的步数走出迷宫(边界处没有墙的地方就是出口)。迷宫总是有4行6列,多解时任意输出一个移动序列即可。

分析:

广搜 + 状态压缩。
因为总墙数只有58,所以可以用一个long long型变量来储存一个状态。
用set来判重。
具体实现见代码。

代码:

 #include <cstdio>
#include <queue>
#include <set>
using namespace std; typedef long long int LLI;
const int dr[] = {-, , , }; //上下左右
const int dc[] = {, , -, };
const char dir[+] = "NSWE"; struct NODE {
int r, c, f, pre; //所在行,所在列,父方向,父结点
char d; //移动方向
LLI state; //当前状态
} node[]; int wall[][][]; //wall[r][c][d] : 第r行第c列d方向的墙的编号 void constant(){
/* 给墙编号时墙的储存方式:
_ _ _
|_|_|_|
|_|_|_|
|_|_|_|
*/
const int cdr[] = {-, , , }; //上下左右
const int cdc[] = {, , -, };
int id = , code[+][+];
for(int c = ; c < ; c += ) code[][c] = id++; //给每一堵墙编号
for(int r = ; r < ; r++){
for(int c = ; c < ; c++) code[r][c] = id++;
}
for(int r = ; r < ; r++){ //获取wall数组
for(int c = ; c < ; c += ){
int t = r - , i = (c - ) / ;
for(int d = ; d < ; d++){
int fr = r + cdr[d], fc = c + cdc[d];
wall[t][i][d] = code[fr][fc];
}
}
}
} void output(int n){ //输出路径
if(node[n].pre) output(node[n].pre);
printf("%c", node[n].d);
} void bfs(){
node[].f = -;
set<LLI> S[][];
S[node[].r][node[].c].insert(node[].state);
queue<int> Q;
Q.push();
int np = ;
while(Q.size()){
int f = Q.front(); Q.pop();
int r = node[f].r;
int c = node[f].c;
LLI& s = node[f].state;
for(int d = ; d < ; d++){
if(d == node[f].f) continue; //避免向父方向返回
LLI state = s;
bool valid = true;
int fr = r + dr[d], fc = c + dc[d];
if(state & 1LL << wall[r][c][d]){ //若前面有墙
if(fr < || fr > || fc < || fc > ) valid = false; //超出边界
else if(state & 1LL << wall[fr][fc][d]) valid = false; //多堵墙连续
else{ //移动该墙
state |= 1LL << wall[fr][fc][d];
state ^= 1LL << wall[r][c][d];
}
}
if(!valid) continue;
if(fr < || fr > || fc < || fc > ){ //找到出口
node[np].d = dir[d];
node[np].pre = f;
output(np);
printf("\n");
return;
}
if(S[fr][fc].count(state)) continue;
S[fr][fc].insert(state);
node[np].r = fr;
node[np].c = fc;
node[np].f = d ^ ; //d的相反方向
node[np].d = dir[d];
node[np].pre = f;
node[np].state = state;
Q.push(np++);
}
}
} int main(){
constant();
const int wei[] = {, , , };
while(scanf("%d%d", &node[].c, &node[].r) && node[].r){
node[].r--; node[].c--; node[].state = ;
for(int r = ; r < ; r++){
for(int c = ; c < ; c++){
int n;
scanf("%d", &n);
for(int d = ; d < ; d++){ //判断上下左右是否有墙
if(n & wei[d]) node[].state |= 1LL << wall[r][c][d];
}
}
}
bfs();
}
return ;
}

UVa 10384 - The Wall Pushers的更多相关文章

  1. UVA - 10384 The Wall Pusher(推门游戏)(IDA*)

    题意:从起点出发,可向东南西北4个方向走,如果前面没有墙则可走:如果前面只有一堵墙,则可将墙向前推一格,其余情况不可推动,且不能推动游戏区域边界上的墙.问走出迷宫的最少步数,输出任意一个移动序列. 分 ...

  2. UVA10384-The Wall Pushers(迭代加深搜索)

    Problem UVA10384-The Wall Pushers Accept: 199   Submit: 1546Time Limit: 10000 mSec Problem Descripti ...

  3. UVA-10384 The Wall Pushers (IDA*)

    题目大意:走迷宫,遇到墙时可以推着墙走,但墙后还是墙时便不能推.求出一条任意的最短路径. 题目分析:这道题出的比较人性,输入的时候便是将四周的墙用二进制数表示好了,其实这样减轻了做题人的负担.IDA* ...

  4. UVa 900 - Brick Wall Patterns

    题目大意:用1*2的砖头建n*2的墙,问有多少种不同的砖头排列方式?与斐波那契序列相似. #include <cstdio> #define MAXN 60 #define N 50 un ...

  5. 【暑假】[深入动态规划]UVa 10618 Fixing the Great Wall

    UVa 10618 Fixing the Great Wall 题目:  http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=361 ...

  6. UVa 11040 (水题) Add bricks in the wall

    题意: 45块石头如图排列,每块石头上的数等于下面支撑它的两数之和,求其余未表示的数. 分析: 首先来计算最下面一行的数,A71 = A81 + A82 = A91 + 2A92 + A93,变形得到 ...

  7. UVa 1303 - Wall

    题目:有非常多点.修一座最短的围墙把素有点围起来,使得全部点到墙的距离不小于l. 分析:计算几何,凸包. 假设.没有距离l的限制.则答案就是凸包的周长了.有了距离限制事实上是添加了2*π*l. 证明: ...

  8. UVA 11040 Add bricks in the wall

    https://vjudge.net/problem/UVA-11040 找规律 #include<cstdio> using namespace std; ][]; int main() ...

  9. UVA 11040 Add bricks in the wall(线性组合)

    砖块上的数字最终都可以看作是最后一行的线性组合,独立变元最多9个. 这类题的一般做法,线性组合都可以列出方程然后高斯消元. 对于这道题,只要确定最后一行剩下的4个变量就好了,对于最后一行的j位置,它对 ...

随机推荐

  1. Html上传大文件

    1. <input type="file" id="file" /> <progress id="></progress ...

  2. out参数

             out参数: 参数在方法的内部必须为其赋值:可以同时返回不同类型的值:                           在Main方法里定义,在方法里赋值:          输 ...

  3. C#语言-03.逻辑控制语句

    a. 逻辑控制语句: i. 条件语句:先对条件判断,然后根据判断结果执行不同的分支 . If 和 if-else:判断“布尔表达式的值”来决定执行那个代码块 a. 语法:if(布尔表达式){ b. 布 ...

  4. [PHP] Oauth授权和本地加密

    1.Oauth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方 关键字:appKey appSecre ...

  5. flask路由末端带斜线和不带斜线的区别

    路由末端带有“/” app.route('/test/') 在浏览器中输入http://127.0.0.1:5000/test/ 和http://127.0.0.1:5000/test都能访问 路由末 ...

  6. RabbitMQ基础--总结

    一. RabbitMQ的五种工作场景: 1. 单发单收 2. 单发送多接收 +++++++++++++++++++++前面两种没有使用exchange++++++++++++++++++ 3. Pub ...

  7. 使用JS完成首页轮播图效果

    获取document.getElementById("id名称"); 事件onload 定时操作setInterval("changeImg()",3000); ...

  8. Angular的生命周期钩子

    没有什么不能用一张图来解决.

  9. 移动端 line-height 不垂直居中问题

    本文是从简书复制的, markdown语法可能有些出入, 想看"正版"和更多内容请关注 简书: 小贤笔记 一般情况下, 我们把 line-height 的值设置为 height 的 ...

  10. cookie结合js 实现记住的拖拽

    哈喽!!!我胡汉三又回来啦!!!有木有记挂挪啊!咱们今天说一个 cookie结合JS的小案例哦! 话不多说直接上代码: <!DOCTYPE html> <html> <h ...