• A*算法-历届试题 九宫重排


     历届试题 九宫重排  

    时间限制:1.0s   内存限制:256.0MB
          
    问题描述
      如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。

      我们把第一个图的局面记为:12345678.
      把第二个图的局面记为:123.46758
      显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
      本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
    输入格式
      输入第一行包含九宫的初态,第二行包含九宫的终态。
    输出格式
      输出最少的步数,如果不存在方案,则输出-1。
    样例输入
    12345678.
    123.46758
    样例输出
    3
    样例输入
    13524678.
    46758123.
    样例输出
    22
     
     
    fuck啊,只对了80%;骚年努力!没有过不去的坎,没有A不掉的题!
    #define _CRT_SECURE_NO_DEPRECATE
    //A*八数码问题
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<cmath>
    #define MAX 1
    using namespace std;
    
    int dx[4] = { 0, 0, 1, -1 }, dy[4] = { 1, -1, 0, 0 };
    
    class NODE{
    public:
        NODE(){ memset(m, 0, sizeof(m)); flag = f = g = h = 0; par = NULL; }
        ~NODE(){}
        char m[3][3];
        //矩阵对应的十进制数
        int flag;
        //估价函数
        int f, g, h;
        //空格坐标
        int tx, ty;
        //父节点
        NODE *par;
        //转换函数
        void m2f(){
            flag=0;
            for(int i=0;i<3;i++){
                for(int j=0;j<3;j++){
                    if(m[i][j]!='.')flag = 10*flag+(m[i][j]-'0');
                    else { flag *= 10; tx = i; ty = j; }
                }
            }
        }
        void init(char *c){
            int i=0;
            for(int j=0;j<3;j++)for(int k=0;k<3;k++)m[j][k]=c[i++];
            m2f();
        }
        //计算f
        void calf(NODE T){
            //h是与目标位置不同数的个数
            for (int i = 0; i < 3; i++)for (int j = 0; j < 3; j++)if (m[i][j] != T.m[i][j])h++;
            
            //h:离对应点的距离
            for (int i = 0; i < 3; i++)for (int j = 0; j < 3; j++){
                for (int k = 0; k < 3; k++)for (int l = 0; l < 3; l++)
                    if (m[i][j] == T.m[k][l]){ h += abs(k + l - i - j); }
            }
        
            if (par != NULL){ g = par->g + 1; f = g + h; }
            else f = h;
        }
        void print(){
            printf("%d
    ",flag);
        }
    };
    
    NODE orig,targ;
    
    //Open表中按f从小到大排序
    struct great{
        bool operator()(NODE N1,NODE N2){
            return N1.f > N2.f;
        }
    };
    
    //Open表和Close表
    priority_queue<NODE,vector<NODE>, great> OList;
    vector<NODE> CList;
    vector<NODE>::iterator itor;
    //A*
    void AStar(){
        int step = 0;
        char temp;
        //找到结果
        bool find = false;
        OList.push(orig);
        //如果Open表空,无解
        while (!OList.empty()){
            //把Open表第一个取出,记为n,加入Close表
            NODE n = OList.top(); OList.pop();
            CList.push_back(n);
            //n是否为目标节点,是则成功退出
            if (n.h == 0){ find = true; step = n.g; break; }
            //n是否可扩展
            for (int i = 0; i < 4; i++){
                int x = n.tx + dx[i], y = n.ty + dy[i];
                if (x>-1 && x<3 && y>-1 && y < 3){
                    NODE t;
                    for (int i = 0; i < 3; i++)for (int j = 0; j < 3; j++)t.m[i][j] = n.m[i][j];
                    t.tx = x; t.ty = y;
                    temp = t.m[n.tx][n.ty];
                    t.m[n.tx][n.ty] = t.m[x][y];
                    t.m[x][y] = temp;
                    t.m2f();
                    t.par = &n;
                    t.calf(targ);
                    if (n.par == NULL || t.flag != n.par->flag){
                        bool inCL = false;
                        for (itor = CList.begin(); itor != CList.end(); itor++){
                            if (t.flag == itor->flag){ inCL = true; break; }
                        }
                        if (!inCL)OList.push(t);
                    }
                }
            }
        }
        if (find){
            printf("%d
    ", step);
        }
        else{
            printf("-1
    ");
        }
    }
    
    int main()
    {
        char c[10];
        //while(1){
            gets(c);
            orig.init(c);
            gets(c);
            targ.init(c);
            orig.calf(targ);
    
            AStar();
        //}
        return 0;
    }

     

    用set来设Close表,结果可以在1s内出来,但是结果是错的,还是80%对了只。

    #define _CRT_SECURE_NO_DEPRECATE
    //A*八数码问题
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<set>
    #include<vector>
    #include<cmath>
    #include<algorithm>
    #define MAX 1
    using namespace std;
    
    int dx[4] = { 0, 0, 1, -1 }, dy[4] = { 1, -1, 0, 0 };
    
    class NODE{
    public:
        NODE(){ memset(m, 0, sizeof(m)); flag = f = g = h = 0; par = NULL; }
        ~NODE(){}
        char m[3][3];
        //矩阵对应的十进制数
        int flag;
        //估价函数
        int f, g, h;
        //空格坐标
        int tx, ty;
        //父节点
        NODE *par;
        //转换函数
        void m2f(){
            flag=0;
            for(int i=0;i<3;i++){
                for(int j=0;j<3;j++){
                    if(m[i][j]!='.')flag = 10*flag+(m[i][j]-'0');
                    else { flag *= 10; tx = i; ty = j; }
                }
            }
        }
        void init(char *c){
            int i=0;
            for(int j=0;j<3;j++)for(int k=0;k<3;k++)m[j][k]=c[i++];
            m2f();
        }
        //计算f
        void calf(NODE T){
            //h是与目标位置不同数的个数
            for (int i = 0; i < 3; i++)for (int j = 0; j < 3; j++)if (m[i][j] != T.m[i][j])h++;
    
            //h:离对应点的距离
            for (int i = 0; i < 3; i++)for (int j = 0; j < 3; j++){
                for (int k = 0; k < 3; k++)for (int l = 0; l < 3; l++)
                    if (m[i][j] == T.m[k][l]){ h += abs(k + l - i - j); }
            }
    
            if (par != NULL){ g = par->g + 1; f = g + h; }
            else f = h;
        }
        void print(){
            printf("%d
    ",flag);
        }
    };
    
    NODE orig,targ;
    
    //Open表中按f从小到大排序
    struct great{
        bool operator()(NODE N1,NODE N2){
            return N1.f > N2.f;
        }
    };
    
    //Open表和Close表
    priority_queue<NODE, vector<NODE>, great> OList;
    //vector<NODE> CList;
    //vector<NODE>::iterator itor;
    set<int> cList;
    set<int>::iterator iter;
    
    bool ccmp(NODE n1,NODE n2){
        //便于二分查找
        return n1.flag<n2.flag;
    }
    //A*
    void AStar(){
    
        int step = 0;
        char temp;
        //找到结果
        bool find = false;
        OList.push(orig);
        //如果Open表空,无解
        while (!OList.empty()){
            //把Open表第一个取出,记为n,加入Close表
            NODE n = OList.top(); OList.pop();
            //CList.push_back(n);
            //CList[++clen]=n;
            cList.insert(n.flag);
            //n是否为目标节点,是则成功退出
            if (n.h == 0){ find = true; step = n.g; break; }
            //n是否可扩展
            for (int i = 0; i < 4; i++){
                int x = n.tx + dx[i], y = n.ty + dy[i];
                if (x>-1 && x<3 && y>-1 && y < 3){
                    NODE t;
                    for (int i = 0; i < 3; i++)for (int j = 0; j < 3; j++)t.m[i][j] = n.m[i][j];
                    t.tx = x; t.ty = y;
                    temp = t.m[n.tx][n.ty];
                    t.m[n.tx][n.ty] = t.m[x][y];
                    t.m[x][y] = temp;
                    t.m2f();
                    t.par = &n;
                    t.calf(targ);
                    if (n.par == NULL || t.flag != n.par->flag){
                        bool inCL = false;
    //                    for (itor = CList.begin(); itor != CList.end(); itor++){
    //                        if (t.flag == itor->flag){ inCL = true; break; }
    //                    }
                        /* c1=0;c2=clen;
                        sort(CList,CList+clen+1,ccmp);
                        while(c1<c2){
                            mid=(c1+c2)/2;
                            if(CList[mid].flag>t.flag)c2=mid-1;
                            else if(CList[mid].flag<t.flag)c1=mid+1;
                            else if(CList[mid].flag==t.flag){inCL=true;break;}
                        } */
                        iter=cList.find(t.flag);
                        if(iter!=cList.end())inCL=true;
                        if (!inCL)OList.push(t);
                    }
                }
            }
        }
        if (find){
            printf("%d
    ", step);
        }
        else{
            printf("-1
    ");
        }
        //printf("%d
    ",CList.size());
    }
    
    //逆序对是否同偶或同奇
    bool comp(int x, int y);
    
    int main()
    {
        char c[10];
        //while(1){
            gets(c);
            orig.init(c);
            gets(c);
            targ.init(c);
            orig.calf(targ);
            if(comp(orig.flag, targ.flag))
                AStar();
            else printf("-1
    ");
        //}
        return 0;
    }
    
    inline bool comp(int x, int y){
        int t1[8],t2[8], i1=0,i2=0, m = 100000000, h;
        while(x){
            h=x/m;
            if(h>0)t1[i1++]=h;
            x%=m;
            m/=10;
        }
        m = 100000000;
        while(y){
            h=y/m;
            if(h>0)t2[i2++]=h;
            y%=m;
            m/=10;
        }
        /*for(int i=0;i<8;i++)printf("%4d",t1[i]);
        printf("
    ");
        for(int i=0;i<8;i++)printf("%4d",t2[i]);
        printf("
    ");*/
        m=0;h=0;
        for(int i=0;i<8;i++)for(int j=i+1;j<8;j++){
            if(t1[i]>t1[j])m++;
            if(t2[i]>t2[j])h++;
        }
        //printf("%d
    %d
    ",m,h);
        if(h%2==m%2)return true;
        else return false;
    }
    世上无难事,只要肯登攀。
  • 相关阅读:
    C++同步串口通信
    python描述符详解
    python属性访问
    python简单计时器实现
    python时间模块详解(time模块)
    python魔法方法大全
    python类与对象各个算数运算魔法方法总结
    python里的魔法方法1(构造与析构)
    Python 函数修饰符(装饰器)的使用
    python类与对象的内置函数大全(BIF)
  • 原文地址:https://www.cnblogs.com/littlehoom/p/3602217.html
Copyright © 2020-2023  润新知