链接:

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. C#操作Redis List 列表

    /// <summary> /// Redis 列表 /// </summary> public static void Redis_List() { RedisClient ...

  2. 原创:微信小程序java实现AES解密并获取unionId

    来自:微信小程序联盟 如果大家使用小程序的同时还在使用公众号的话,可能会用到unionId这种功能,由于公司业务需要,我们需要使用unionId,具体使用方法,请参考微信开放平台的说明,但是在微信小程 ...

  3. input:checkbox 是否被选中?

    <input type="checkbox" id="checkbox1"> <script> $(function(){ $(&quo ...

  4. 不能修改列 "。。",因为它是计算列,或者是 UNION 运算符的结果。

    修改Mapping this.Property(t => t...).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotatio ...

  5. 文档类型DTD,DOCTYPE和浏览器模式

    出处:http://blog.csdn.net/freshlover/article/details/11616563 浏览器从服务端获取网页后会根据文档的DOCTYPE定义显示网页,如果文档正确定义 ...

  6. Boxlayout中button改变大小

    需要先设置maximunsize neuStart.setBorder(BorderFactory.createRaisedBevelBorder()); neuStart.setMaximumSiz ...

  7. 嵌套Golang对象的初始化

      比如有这样一个对象: type ProductConfig struct {     Site map[string]string } 对应的初始化可以如下写: var pc ProductCon ...

  8. Algorithm——两数之和

    题目: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数组中 ...

  9. mysql case when & concat & SUBSTRING_INDEX & not & having 使用的小case

    1. 代码 SELECT a.id, a.activity_name, ( CASE WHEN a.activity_end_time > now() THEN '参与中' ELSE ( CAS ...

  10. 洛谷P1155 双栈排序(贪心)

    题意 题目链接 Sol 首先不难想到一种贪心策略:能弹则弹,优先放A 然后xjb写了写发现只有\(40\),原因是存在需要决策的情况 比如 \(A = {10}\) \(B = {8}\) 现在进来一 ...