Rush Hour Puzzle

2019-2020 ICPC Asia Taipei-Hsinchu Regional Contest的A题

题目
Rush Hour is a puzzle game invented by Nob Yoshigahara in the 1970s. It is now being manufactured by ThinkFun. The board is a 6 × 6 grid with grooves in the tiles to allow vehicles to slide. Cars and trucks are both one square wide, but cars are two squares long and trucks are three squares long. Vehicles can only be moved forward or backward along a straight
line on the grid. The goal of the game is to get the only red car totally out through the exit of the board by moving the other vehicles out of its way. Figure 1 gives an example of Rush Hour puzzle.
在这里插入图片描述
We give each vehicle of a puzzle a unique id, numbered from 1 to the number of vehicles, in which the red car’s id is 1. The board information of a puzzle is represented by a 6 × 6 matrix,named board matrix. Each entry of a board matrix is the id of the vehicle placed on that groove, and the entries are filled with 0 if there exists no vehicle on those grooves. The exit of the board is located at the right end side of the 3rd row. Figure 2 shows the board matrix corresponding to the puzzle in Figure 1.
Moving a piece (car or truck) by one unit (a groove) is called a step. A puzzle is easy if it can be solved (the red car totally out through the exit of the board) in no more than 10 steps. Please write a program to judge whether a puzzle is easy or not.
两组样例
输入

2 2 0 0 0 7
3 0 0 5 0 7
3 1 1 5 0 7
3 0 0 5 0 0
4 0 0 0 8 8
4 0 6 6 6 0

输出

-1

输入

0 2 0 6 6 0
0 2 0 0 7 0
0 3 1 1 7 0
0 3 4 4 8 0
0 5 5 5 8 0
0 0 0 0 0 0

输出

6

题目大意

给你一个6 * 6的华容道,求十步之内是否有解.

题目思路

华容道内最多有十个车每个车可以沿摆放的方向两边移动,用bfs搜索移动每个车的
状态,把这个状态用哈希记录下来前面搜过的就不用再搜了。

ac代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
const double eps=1e-5;
map<ull,int> ha; //哈希的值用map存一下 
struct node{ // 每个状态都是一个node 
	int a[7][7];
};
ull pp[40]; //哈希函数 
ull hh(node a){
	ull sum = 0;
	ull cnt = 0;
	for(int i = 1; i <= 6; i ++){
		for(int j = 1; j <= 6;j ++){
			sum += a.a[i][j] * pp[cnt];
			cnt ++; 
		}
	}
	return sum;
}
struct car{
	int len;
	bool x;
};
node st;
car car1[15];
int ans = -1;
typedef pair<node,int> PII;
void bfs(){
	queue<PII> q;
	q.push({st,0});
	ha[hh(st)] = true;
	while(!q.empty()){
		node now = q.front().first;
		int step = q.front().second;
		q.pop();
		if(now.a[3][6] == 1){ //红车走到边缘就可以结束搜索 
			ans = step + 2;//最后两步走出去直接加上 
			return;
		}
		if(step >= 8){
			continue;
		}
		bool vis[11];
		node temp;
		for(int i = 1; i <= 6; i ++){
			for(int j = 1; j <= 6; j ++){
				temp.a[i][j] = now.a[i][j];
			}
		}
		for(int i = 1; i <= 10; i ++) vis[i] = false;
		for(int i = 1; i <= 6; i ++){
			for(int j = 1; j <= 6; j ++){
				int t = now.a[i][j];
				if(t == 0) continue; 
				if(vis[t]) continue;
				vis[t] = true;
				if(!car1[t].x){
					bool f = false;
					if(i > 1){
						if(temp.a[i - 1][j] == 0){
							temp.a[i - 1][j] = t;
							temp.a[i + car1[t].len - 1][j] = 0;
							f = true;
							if(!ha[hh(temp)]){
								ha[hh(temp)] = true;
								q.push({temp,step + 1});
							}
						}	
					}
					if(f == true){
						temp.a[i - 1][j] = 0;
						temp.a[i + car1[t].len - 1][j] = t;
					}
					if(i + car1[t].len <= 6){
						if(temp.a[i + car1[t].len][j] == 0){
							temp.a[i][j] = 0;
							temp.a[i + car1[t].len][j] = t;
							if(!ha[hh(temp)]){
								ha[hh(temp)] = true;
								q.push({temp,step + 1});
							}
							temp.a[i][j] = t;
							temp.a[i + car1[t].len][j] = 0;
						}		
					}
				}else{
					bool f = false;
					if(j > 1){
						if(temp.a[i][j - 1] == 0){
							temp.a[i][j - 1] = t;
							temp.a[i][j + car1[t].len - 1] = 0;
							f = true;
							if(!ha[hh(temp)]){
								ha[hh(temp)] = true;
								q.push({temp,step + 1});
							}
						}	
					}
					if(f == true){
						temp.a[i][j - 1] = 0;
						temp.a[i][j + car1[t].len - 1] = t;
					}
					if(j + car1[t].len <= 6){
						if(temp.a[i][j + car1[t].len] == 0){
							temp.a[i][j] = 0;
							temp.a[i][j + car1[t].len] = t;
							if(!ha[hh(temp)]){
								ha[hh(temp)] = true;
								q.push({temp,step + 1});
							}
							temp.a[i][j] = t;
							temp.a[i][j + car1[t].len] = 0;
						}	
					}
				}
			}
		}
	}
}
int main(){
	for(int i = 1; i <= 6;i ++){
		for(int j = 1; j <= 6; j ++){
			scanf("%d",&st.a[i][j]);
		}
	}
	bool vis[11];
	pp[0] = 1;
	for(int i = 1; i < 40; i ++){
		pp[i] = pp[i - 1] * 131;
	}
	for(int i = 1; i <= 10; i ++) vis[i] = false;
	for(int i = 1; i <= 6; i ++){ // 记录每个车的状态, 
		for(int j = 1; j <= 6; j ++){
			if(st.a[i][j] == 0) continue;
			if(vis[st.a[i][j]]) continue;
			vis[st.a[i][j]] = true;
			int x = i, y = j;
			int cnt = 0;
			while(y <= 6 && st.a[x][y] == st.a[i][j]){
				cnt ++;
				y ++;
			}
			if(cnt > 1){
				car1[st.a[i][j]].len = cnt;
				car1[st.a[i][j]].x = true;
			}
			x = i,y = j;
			cnt = 0;
			while(x <= 6 && st.a[x][y] == st.a[i][j]){
				cnt ++;
				x ++;
			}
			if(cnt > 1){
				car1[st.a[i][j]].len = cnt;
				car1[st.a[i][j]].x = false;
			}
		}
	}
	bfs();
	if(ans == -1){
		printf("-1\n");
	}else{
		printf("%d\n",ans);
	}
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

顺序并不响影阅读

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值