• 八数码(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');
    }

    //

  • 相关阅读:
    泛型冒泡排序继承IComparable接口
    C#中枚举与位枚举的区别和使用
    C#中把二维数组转为一维数组
    一维数组的冒泡排序
    C#控制台的两个二维数组相加
    vs2019连接MySql的连接字符串
    Ajax方法请求WebService实现多级联动
    kafka-manager无法启动解决方法
    SQL优化————Insert
    读写锁
  • 原文地址:https://www.cnblogs.com/JMDWQ/p/2519728.html
Copyright © 2020-2023  润新知