zoukankan      html  css  js  c++  java
  • POJ 1077 HDU 1043 Eight (IDA*)

    题意就不用再说明了吧......如此经典

    之前想用双向广搜、a*来写,但总觉得无力,现在用IDA*感觉其他的解法都弱爆了..............想法活跃,时间,空间消耗很小,给它跪了


    启发式搜索关键还是找估价函数:此题估价函数可大致定性为每个数字(除去x,只要8个数字)当前位置与它期望位置的曼哈顿距离

    即为:v += abs(i - pos[map[i][j] - 1][0]);     v += abs(j - pos[map[i][j] - 1][1]);     大致估算为几十步内得出结果。

    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <string>
    #include <vector>
    #include <set>
    #include <queue>
    #include <stack>
    #include <climits>//形如INT_MAX一类的
    #define MAX 100005
    #define INF 0x7FFFFFFF
    #define REP(i,s,t) for(int i=(s);i<=(t);++i)
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mp(a,b) make_pair(a,b)
    #define L(x) x<<1
    #define R(x) x<<1|1
    # define eps 1e-5
    //#pragma comment(linker, "/STACK:36777216") ///传说中的外挂
    using namespace std;
    
    int pos[9][2] = {  //各个数字的初始位置
        {0,0},{0,1},{0,2},
        {1,0},{1,1},{1,2},
        {2,0},{2,1},{2,2}
    };
    int map[4][4];
    int buff[50];
    char input[11];
    int limit,ok;
    int dx[] = {-1,0,1,0}; //u r d l____0 1 2 3
    int dy[] = {0,1,0,-1};
    char op[] = {'u','r','d','l'};
    
    int h(int x,int y) {
        int v = 0;
        for(int i=0; i<3; i++) {
            for(int j=0; j<3; j++) {
                if(i != x || j != y) {
                    v += abs(i - pos[map[i][j] - 1][0]);
                    v += abs(j - pos[map[i][j] - 1][1]);
                }
            }
        }
        return v;
    }
    
    int dfs(int x,int y,int step,int pre) {
        int hn = h(x,y);
        if(hn == 0) {
            ok = 1;
            return step;
        }
        if(hn + step > limit) return hn + step;
        int minn = INF;
        for(int i=0; i<4; i++) {
            if(abs(i - pre) == 2) continue;
            int xx = x + dx[i];
            int yy = y + dy[i];
            if(xx<0 || xx >=3 || yy<0 || yy >=3) continue;
            buff[step] = i;
            swap(map[x][y],map[xx][yy]);
            int tmp = dfs(xx,yy,step+1,i);
            if(ok) return tmp;
            minn = min(tmp,minn);
            swap(map[x][y],map[xx][yy]);
        }
        return minn;
    }
    
    void IDA_star(int x,int y) {
        ok = 0;
        memset(buff,-1,sizeof(buff));
        while(ok == 0 && limit <= 36) {
            limit = dfs(x,y,0,-111);
        }
        if(ok == 1) {
            for(int i=0; i<limit; i++) printf("%c",op[buff[i]]);
            puts("");
        } else puts("unsolvable");
    }
    
    int main() {
        for(int i=0; i<9; i++) cin >> input[i];
        int t = 0,x,y;
        for(int i=0; i<3; i++) {
            for(int j=0; j<3; j++) {
                if(input[t] == 'x') {
                    map[i][j] = 9;
                    x = i;
                    y = j;
                    t++;
                } else map[i][j] = input[t++] - '0';
            }
        }
        int limit = h(x,y);
        if(limit == 0) {
            puts("");
            return 0;
        }
        IDA_star(x,y);
        return 0;
    }
    

    想吐槽一下杭电的这题.........估计各种无法到达目标的数据,所以在输入时候通过求逆序数对数来判断是否有解,本来是TLE,一下蹦到171ms

    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <string>
    #include <vector>
    #include <set>
    #include <queue>
    #include <stack>
    #include <climits>//形如INT_MAX一类的
    #define MAX 100005
    #define INF 0x7FFFFFFF
    #define REP(i,s,t) for(int i=(s);i<=(t);++i)
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define mp(a,b) make_pair(a,b)
    #define L(x) x<<1
    #define R(x) x<<1|1
    # define eps 1e-5
    //#pragma comment(linker, "/STACK:36777216") ///传说中的外挂
    using namespace std;
    
    int pos[9][2] = {  //各个数字的初始位置
        {0,0},{0,1},{0,2},
        {1,0},{1,1},{1,2},
        {2,0},{2,1},{2,2}
    };
    int map[4][4];
    int buff[50];
    char input[11];
    int limit,ok;
    int dx[] = {-1,0,1,0}; //u r d l____0 1 2 3
    int dy[] = {0,1,0,-1};
    char op[] = {'u','r','d','l'};
    
    int h(int x,int y) {
        int v = 0;
        for(int i=0; i<3; i++) {
            for(int j=0; j<3; j++) {
                if(i != x || j != y) {
                    v += abs(i - pos[map[i][j] - 1][0]);
                    v += abs(j - pos[map[i][j] - 1][1]);
                }
            }
        }
        return v;
    }
    
    int dfs(int x,int y,int step,int pre) {
        int hn = h(x,y);
        if(hn == 0) {
            ok = 1;
            return step;
        }
        if(hn + step > limit) return hn + step;
        int minn = INF;
        for(int i=0; i<4; i++) {
            if(abs(i - pre) == 2) continue;
            int xx = x + dx[i];
            int yy = y + dy[i];
            if(xx<0 || xx >=3 || yy<0 || yy >=3) continue;
            buff[step] = i;
            swap(map[x][y],map[xx][yy]);
            int tmp = dfs(xx,yy,step+1,i);
            if(ok) return tmp;
            minn = min(tmp,minn);
            swap(map[x][y],map[xx][yy]);
        }
        return minn;
    }
    int canget(int a[4][4]) { //这一步省了好多时间 求逆序数对数
        int i,j,sum=0,b[10],k=0;
        for(i=0; i<3; i++) {
            for(j=0; j<3; j++) {
                if(a[i][j] != 9)
                    b[++k]=a[i][j];
            }
        }
        for(i=1; i<=8; i++) {
            for(j=1; j<i; j++) {
                if(b[i]<b[j])sum++;
            }
        }
        if(sum % 2 ==0)return 1;
        else return 0;
    }
    void IDA_star(int x,int y) {
        ok = 0;
        memset(buff,-1,sizeof(buff));
        while(ok == 0 && limit <= 30) {
            limit = dfs(x,y,0,-111);
        }
        if(ok == 1) {
            for(int i=0; i<limit; i++) printf("%c",op[buff[i]]);
            puts("");
        } else puts("unsolvable");
    }
    
    int main() {
        while(cin >> input[0]) {
            //memset(map,0,sizeof(map));
            for(int i=1; i<9; i++) cin >> input[i];
            int t = 0,x,y;
            for(int i=0; i<3; i++) {
                for(int j=0; j<3; j++) {
                    if(input[t] == 'x') {
                        map[i][j] = 9;
                        x = i;
                        y = j;
                        t++;
                    } else map[i][j] = input[t++] - '0';
                }
            }
            limit = h(x,y);
            if(limit == 0) {
                puts("");
                continue;
            }
            if(canget(map))
                IDA_star(x,y);
            else puts("unsolvable");
        }
        return 0;
    }
    


    经过猥琐的测试,limit最小限制在29步....................


  • 相关阅读:
    MyBatis 核心配置综述之 ResultSetHandler
    MyBatis 核心配置综述之 ParameterHandler
    MyBatis 核心配置综述之StatementHandler
    高等数学——手撕牛顿莱布尼茨公式
    用二分法优化动态规划——实现快速决策
    召回、精确、准确,这些让人头大的概念一文全讲清楚
    Python——详解__slots__,property和私有方法
    LeetCode50——一题学会快速幂算法
    Golang——详解Go语言代码规范
    spark——详解rdd常用的转化和行动操作
  • 原文地址:https://www.cnblogs.com/pangblog/p/3275707.html
Copyright © 2011-2022 走看看