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;
}