【链接】 我是链接,点我呀:)
【题意】
在这里输入题意
【题解】
IDA*
保证这次移动的方格不和前一次重复。
然后加一个8数码的剪枝就行了。
->看看当前状态和目标状态有多少个地方是不一样的。
如果当前的步数加上它仍然比答案大。
显然可以剪枝。
因为不同的数目肯定小于等于要移动的数目;
(每次移动最多只能让一个方格还原)
(然后只要记录上面和前面的颜色就好了
剩下一个面的颜色能够通过其他两种颜色推出来。
对面的颜色是相等的。
(这个算法(剪枝)的效率真的超级高。。。
【代码】
#include <bits/stdc++.h>
#define ll long long
using namespace std;
//上 前
//0 1
//0 1 2 3
//E B W R
const int dx[4] = {-1,1,0,0};
const int dy[4] = {0,0,1,-1};
pair<int,int> a[5][5];
int goal[5][5],ans;
int other(int x,int y){
return 6-(x+y);
}
void rotate_left_right(pair<int,int> &x){
pair<ll,ll> temp = x;
x.first = other(temp.first,temp.second);
x.second = temp.second;
}
void rotate_up_down(pair<int,int> &x){
pair<ll,ll> temp = x;
x.first = temp.second;
x.second = temp.first;
}
int gujia(){
int cnt = 0;
for (int i = 1;i <= 3;i++)
for (int j = 1;j <= 3;j++)
if (a[i][j].first!=goal[i][j])
cnt++;
return cnt;
}
void dfs(int dep,int prex,int prey){
int differ = gujia();
if (differ==0){
if (dep < ans){
ans = dep;
return;
}
return;
}
if (dep + differ>ans) return;
int x,y;
for (int i = 1;i <= 3;i++)
for (int j = 1;j <= 3;j++)
if (a[i][j].first==0){
x = i,y = j;
}
for (int i = 0;i < 4;i++){
int tx = x + dx[i],ty = y + dy[i];
if (tx >=1 && tx<=3 && ty>=1 && ty <= 3 &&!(tx==prex && ty==prey)) {
pair<int,int> temp = a[tx][ty];
if (i>1)
rotate_left_right(a[tx][ty]);
else
rotate_up_down(a[tx][ty]);
swap(a[tx][ty],a[x][y]);
dfs(dep+1,x,y);
a[tx][ty] = temp;
a[x][y] = {0,0};
}
}
}
int main(){
#ifdef LOCAL_DEFINE
freopen("rush_in.txt", "r", stdin);
#endif
ios::sync_with_stdio(0),cin.tie(0);
int x,y;
while (cin >> x >> y){
swap(x,y);
if (x==0 && y==0) break;
for (int i = 1;i<=3;i++)
for (int j = 1;j<= 3;j++){
if (i==x && y==j)
a[i][j] = {0,0};
else
a[i][j] = {2,3};
}
for (int i = 1;i <= 3;i++)
for (int j = 1;j <= 3;j++){
char s[3];
cin >> s;
goal[i][j] = 0;
switch(s[0]){
case 'B':goal[i][j] = 1;break;
case 'W':goal[i][j] = 2;break;
case 'R':goal[i][j] = 3;break;
}
}
ans = 31;
dfs(0,-1,-1);
if (ans>=31){
cout << -1 << endl;
}else{
cout << ans << endl;
}
}
return 0;
}