【习题 7-9 UVA-1604】Cubic Eight-Puzzle

【链接】 我是链接,点我呀:)
【题意】

在这里输入题意

【题解】

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;
}
posted @ 2018-01-01 19:24  AWCXV  阅读(292)  评论(0编辑  收藏  举报