八数码(IDA*)

IDA*+曼哈顿 相当快! 通过五组数据总计用时 0.015000 s.

把宏定义中的N和SIZE改一下,就可以处理十五数码问题了,终于修炼到第八层了;

刚开始还是使用结构体定义了状态,写得相当麻烦,后来发现IDA*中不像BFS和A*,只需要考虑一条路,,参考了lym(http://www.cnblogs.com/liyongmou/archive/2010/07/19/1780861.html)的(后面调试的受不了了,对照着此大牛的代码一点点改,最后发现是更新状态时,npos写成了pos……)

# include <stdio.h>

# include <math.h>

# include <string.h>

# include <time.h>



# define MIN(x, y) ((x)<(y) ? (x):(y))



# define N 9

# define DIR_N 4

# define INF 0x7fffffff

# define MAX_DEPTH 1000

# define SIZE 3



char solved;

char start[N], goal[N];

char cur[N];



int bound;

const char md[] = {'u', 'l', 'r', 'd'};

const short int dir[][2] = {{-1,0}, {0,-1}, {0,1}, {1,0}};

char path[MAX_DEPTH];



void move(void);

void solve(void);

char read(char *s);

int IDAstar(void);

char bool_inv(char *s);

int heu(void);

int dfs(int zero_pos, int depth, char direction);

void print_state(char *s);



int main()

{

         freopen("in.txt", "r", stdin);

         freopen("out.txt", "w", stdout);



    while (read(start))

    {

        read(goal);

        memcpy(cur, start, N);

        solve();

    }

    

    printf("time cost %.6lf s.\n", (double)clock()/CLOCKS_PER_SEC);



    return 0;

}



void solve()

{

    int i, depth;



    if (bool_inv(start) != bool_inv(goal)) puts("unsolvable");

    else

    {

        memset(path, -1, sizeof(path));

        depth = IDAstar();

        for (i = 0; path[i]!=-1; ++i)

        {

            putchar(md[path[i]]);

        }

        printf(" %d\n", i);

    }

    //move(); //打印移动过程,调试的时候用的,加上这个总共用时31ms

}



char read(char *s)

{

    char c[5];

    int i;



    if (EOF == scanf("%s", c)) return 0;

    else s[0] = (c[0]=='x' ? 0:c[0]-'0');

    for (i = 1; i < N; ++i)

    {

        scanf("%s", c);

        s[i] = (c[0]=='x' ? 0:c[0]-'0');

    }

    

    return 1;

}



int IDAstar(void)

{

    int i;



    solved = 0;

    bound = heu();



    for (i = 0; start[i] && i < N; ++i) ;



    while (!solved && bound<100)

    {

        bound = dfs(i, 0, -10);

    }



    return bound;

}



int dfs(int pos, int depth, char d)

{

    int h, i, nx, ny, npos, nbound, t;



    h = heu();



    if (depth+h > bound) return depth+h;

    if (h == 0)

    {

       /* printf("depth = %d.\n", depth); */

        solved = 1;

        return depth;

    }



    nbound = INF;

    for (i = 0; i < DIR_N; ++i)

    {

        if (i+d == DIR_N-1) continue;

        nx = pos/SIZE + dir[i][0];

        ny = pos%SIZE + dir[i][1];

        if (0<=nx && nx<SIZE && 0<=ny && ny<SIZE)

        {

            path[depth] = i;

            npos = nx*SIZE + ny;

            cur[pos] = cur[npos]; cur[npos] = 0;    /* 后来一直出错就是这里的原因:pos -> npos */

            t = dfs(npos, depth+1, i);

            if (solved) return t;

            nbound = MIN(nbound, t);

            cur[npos] = cur[pos]; cur[pos] = 0;

        }

    }

    return nbound;

}



int heu(void)            /* return heu(cur_state) */

{

    char ch;

    int i, j, ret;



    ret = 0;

    for (i = 0; i < N; ++i)

    {

        ch = goal[i];

        if (ch == 0) continue;

        for (j = 0; j < N; ++j)

        {

            if (ch == cur[j])

            {

                ret = ret + abs(i/SIZE-j/SIZE) + abs(i%SIZE-j%SIZE);

            }

        }

    }



    return ret;

}



char bool_inv(char *s)

{

    char ch, ret;

    int i, j;



    ret = 0;

    for (i = 0; i < N-1; ++i)

    {

        if ((ch = s[i]) == 0) continue;

        for (j = i+1; j < N; ++j)

        {

            if (s[j] && s[j]<ch) ret = 1 - ret;

        }

    }



    return ret;

}



void move(void)

{

    char ncur[N];

    int i, pos, nx, ny, npos;



    memcpy(ncur, start, N);

    print_state(ncur);

    for (i = 0; start[i] && i<N; ++i) ;

    pos = i;

    for (i = 0; path[i] != -1; ++i)

    {

        nx = pos/SIZE + dir[path[i]][0];

        ny = pos%SIZE + dir[path[i]][1];

        npos = nx*SIZE + ny;

        ncur[pos] = ncur[npos]; ncur[npos] = 0;

        pos = npos;

        print_state(ncur);

    }

}



void print_state(char *s)

{

    int i;



    for (i = 0; i < N; ++i)

    {

        putchar(s[i]+'0');

    }

    putchar('\n');

}

//

你可能感兴趣的:(id)