IDA* 求16宫格拼图

#include <QCoreApplication>
#include <bits/stdc++.h>
#include <iostream>
#include <cstring>
#include <stdio.h>

using namespace std;

#define N 4
#define N2 16
#define LIMIT 100

static const int dx[4] = {-1, 0, 1, 0};
static const int dy[4] = {0, -1, 0, 1};
static const char dir[4] = {'U','L','D','R'};
int MDT[N2][N2];

struct Puzzle
{
    int f[N2];                  //16个位置
    int space;                  //空格的位置
    int MD;
};

Puzzle state;
int limit;                      //深度限制
int path[LIMIT];

int getAllMD(Puzzle pz)
{
    int sum = 0;
    for(int i = 0; i < N2; i++)
    {
        if(pz.f[i] == N2)
            continue;
        sum += MDT[i][pz.f[i]-1];
    }

    return sum;
}


bool isSolve()
{
    for(int i = 0; i < N2; i++)
    {
        if(state.f[i] != i+1)
            return false;
    }

    return true;
}



bool dfs(int depth, int prev)                       //深度和上一步方向
{
    if(state.MD == 0)
        return true;

    if(depth + state.MD > limit)                    //如果当前深度加上启发超过了限制,则进行剪纸
        return false;

    int sx = state.space / N;
    int sy = state.space % N;

    Puzzle tmp;

    for(int r = 0; r < 4; r++)
    {
        int tx = sx + dx[r];
        int ty = sy + dy[r];

        if(tx < 0 || ty < 0 || tx >= N || ty >= N)
            continue;
        if(max(prev, r) - min(prev, r) == 2)            //防止走回去,两个相反的方向相差2
            continue;

        tmp = state;

        state.MD -= MDT[tx*N+ty][state.f[tx*N+ty] - 1];

        state.MD += MDT[sx*N+sy][state.f[tx*N+ty] - 1];

        swap(state.f[tx*N+ty], state.f[sx*N+sy]);

        state.space = tx*N+ty;

        if(dfs(depth+1, r))                         //如果这一步探索成功           
        {
            path[depth] = r;
            return true;
        }

        state = tmp;                                //退回原来的状态
    }

    return false;
}


string iterative_deepening(Puzzle in)
{
    in.MD = getAllMD(in);                           //初始状态下的曼哈顿距离

    for(limit = in.MD; limit <= LIMIT; limit++)
    {
        state = in;
        if(dfs(0, -100))
        {
            string ans = "";

            for(int i = 0; i < limit; i++)
                ans += dir[path[i]];

            return ans;
        }
    }

    return "unsolvable";
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    freopen("G:\\data.txt", "r", stdin);

    for(int i = 0; i < N2; i++)
    {
        for(int j = 0; j < N2; j++)
        {
            MDT[i][j] = abs[i/N-j/N] + abs(i%N-j%N);
        }
    }

    Puzzle in;

    for(int i = 0; i < N2; i++)
    {
        cin >> in.f[i];
        if(in.f[i] == 0)
        {
            in.f[i] = N2;
            in.space = i;
        }
    }

    string ans = iterative_deepening(in);

    cout << ans << " " <<  ans.size() << endl;

    return a.exec();
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值