隐藏
「清北国庆模拟D1T3」方格图 - 搜索 | Bill Yang's Blog

路终会有尽头,但视野总能看到更远的地方。

0%

「清北国庆模拟D1T3」方格图 - 搜索

题目大意

众所周知,八数码问题是一个非常难的问题,但是 Yjq 非常有面子,他把这道题简化了一番。现在给了你一个3 × 3的方格图,你的目标是通过不断移动使得相邻颜色的块形成联通块。你每次的移动方式是选择一列或者一行进行置换滑动(这个解释起来比较麻烦,看下面的图就懂了)。所谓置换滑动,就是所有格子沿着给定的方向顺次移动,最后一个格子会被置换到最前面的过程。现在给定整个方格图,以及每个格子是否能够移动,求使得相同颜色联通的最小步数。


题目分析

搜索显神威,暴力出奇迹!

直接暴力宽搜,每一次判断是否连成连通块就可以了。

我的代码中间运用了一些异或的技巧,相信大家都能看懂。


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
inline const int Get_Int() {
int num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
const int Dirx[]= {-1,1,0,0},Diry[]= {0,0,-1,1};
struct Color {
int c[5];
};
struct Point {
int step;
Color a[4][4];
Point() {step=0,memset(a,0,sizeof(a));}
} st;
bool vst[5][5][5],vstc[5],vstx[5],vsty[5];
void Check2(Point a,int sx,int sy,int sd) {
queue<pair<int,pair<int,int> > >Q;
Q.push(make_pair(sx,make_pair(sy,sd)));
vst[sx][sy][sd]=1;
while(!Q.empty()) {
int x=Q.front().first,y=Q.front().second.first,d=Q.front().second.second;
Q.pop();
for(int i=0; i<4; i++)
if(d!=i&&d!=(i^1)&&!vst[x][y][i]&&a.a[x][y].c[i]==a.a[x][y].c[d]) {
vst[x][y][i]=1;
Q.push(make_pair(x,make_pair(y,i)));
}
int nx=x+Dirx[d],ny=y+Diry[d],nd=d^1;
if(nx>=1&&nx<=3&&ny>=1&&ny<=3&&!vst[nx][ny][nd]&&a.a[nx][ny].c[nd]==a.a[x][y].c[d]) {
vst[nx][ny][nd]=1;
Q.push(make_pair(nx,make_pair(ny,nd)));
}
}
}
bool Check(Point a) {
memset(vst,0,sizeof(vst));
memset(vstc,0,sizeof(vstc));
for(int i=1; i<=3; i++)
for(int j=1; j<=3; j++)
for(int k=0; k<4; k++)
if(!vstc[a.a[i][j].c[k]]) {
vstc[a.a[i][j].c[k]]=1;
Check2(a,i,j,k);
} else if(!vst[i][j][k])return false;
return true;
}
const int mod=99995999;
bool Hash[mod+5];
int Get_Hash(Point a) {
int sum=0;
for(int i=1; i<=3; i++)
for(int j=1; j<=3; j++)
for(int k=0; k<4; k++)
sum=((long long)sum*10007+a.a[i][j].c[k])%mod;
return sum;
}
Point Change(Point a,int pos,int d) {
Point b=a;
b.step++;
if(d<=1&&vsty[pos])return a;
if(d>1&&vstx[pos])return a;
if(d<=1) {
for(int i=1; i<=3; i++) {
int nx=(i+Dirx[d])%3;
if(nx==0)nx=3;
b.a[nx][pos]=a.a[i][pos];
}
return b;
} else {
for(int i=1; i<=3; i++) {
int ny=(i+Diry[d])%3;
if(ny==0)ny=3;
b.a[pos][ny]=a.a[pos][i];
}
return b;
}
}
void Bfs() {
queue<Point>Q;
Q.push(st);
if(Check(st)) {
puts("0");
return;
}
Hash[Get_Hash(st)]=1;
while(!Q.empty()) {
Point Now=Q.front();
Q.pop();
for(int i=1; i<=3; i++)
for(int j=0; j<4; j++) {
Point Next=Change(Now,i,j);
int hash1=Get_Hash(Next);
if(!Hash[hash1]) {
Hash[hash1]=1;
Q.push(Next);
if(Check(Next)) {
printf("%d\n",Next.step);
return;
}
}
}
}
}
char M[205];
int main() {
M['R']=0,M['G']=1,M['B']=2,M['O']=3;
for(int i=1; i<=3; i++)
for(int j=1; j<=3; j++) {
char s[15];
scanf("%s",s);
st.a[i][j].c[0]=M[s[0]];
st.a[i][j].c[1]=M[s[1]];
st.a[i][j].c[2]=M[s[2]];
st.a[i][j].c[3]=M[s[3]];
if(s[4]=='1')vstx[i]=vsty[j]=1;
}
Bfs();
return 0;
}
姥爷们赏瓶冰阔落吧~