一、思路很简单,搜索。对于每一种状态,利用康托展开编码成一个整数。于是,状态就可以记忆了。

二、在搜索之前,可以先做个优化,对于逆序数为奇数的序列,一定无解。

三、搜索方法有很多。

  1、最普通的:深搜、广搜。在这题里面,这两个方法直接TLE。所以,我后面没有贴超时的代码。

  2、既然1超时,那就预处理出所有状态,用map存储,然而,map的insert(使用[]是一样的)实在太慢了,也超时。

  3、在1的基础上,优化一下,得到:IDA*,双向广搜,A*。

  3、IDA*我没尝试,不过感觉没有A*快。另外,双向广搜可以加优化,在HDU上可以快大概300ms,就是:对于某一个方向,在开始BFS时,如果当前的队列里面状态个数很多,而另外一个队列里面相对较少,那么,把搜索方面换成另一边。这样,不至于出现两个队列的状态个数相差太远以至于退化成单向BFS的情况。当然,这个题两个队列中的状态都是比较均匀的,即使不加优化,效果也不会太差。

  4、不管用的是什么搜索,搜索过程中,多个样例经历经历相同的状态是非常有可能的,所以,理论上来说,可以加缓存,也就是其实不管是什么样例,只要序列确定,得到的整数编码一定是确定的,所以,理论上来说,加缓存可以加速,然而, 不知为何,这题,加了缓存还更慢。多半是因为我的缓存用的是C++ STL吧。

四、注意点

  1、双向BFS加优化时,C++的queue的size()的返回值类型是unsigned int,直接相减,会发生溢出的情况, 导致size()小的队列大小一直不变,size()大的队列一直在扩大,也就是退化成了单向BFS了。T_T。所以,为了防止这种情况发生,在size相减之前,用两个int变量先存储好这两个队列的size。否则,会很坑。

  2、在循环中开辟新指针,每一次循环开辟的指针值都一样,如代码所示。

#include<bits/stdc++.h>
using namespace std;

typedef struct Foo{
    int v1, v2;
    Foo(int _v1,int _v2){
        v1 = _v1;
        v2 = _v2;
    }
    Foo(){}
}Node;

set<Node*> s;
int main(){
    ;i < ;++i){
        Node node = Node(i, i);
        s.insert(&node);
    }
    printf("%d\n", s.size());
}

输出结果会是1,而不是5。特别要注意。而如果这么写:

#include<bits/stdc++.h>
using namespace std;

typedef struct Foo{
    int v1, v2;
    Foo(int _v1,int _v2){
        v1 = _v1;
        v2 = _v2;
    }
    Foo(){}
}Node;

set<Node*> s;
int main(){
    ;i < ;++i){
        Node* pnode = new Node(i, i);
        s.insert(pnode);
    }
    printf("%d\n", s.size());
}

因为C++没有自动垃圾回收,所以,很有可能会出现MLE的情况。因此,ACM竞赛中,尽可能地不要使用指针。

  3、C++的容器,map、string、vector之类的,慢!慢!慢!如果条件允许,时间又压得比较紧,特别是像string这种的,最好还是用C语言原生的字符串数组,虽然麻烦些,但是比string快不只一点点。

五、源代码

  1、双向BFS(队列容量均衡优化)

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
];

void init() {
    facts[] = facts[] = ;
    ; i <= ; ++i)facts[i] = facts[i - ] * i;
}

int encode(vector<int>& seq) {
    ;
    int num = seq.size();
    ; i < num - ; ++i) {
        ;
        ; j < i; ++j) {
            if(seq[j] < seq[i])--cnt;
        }
        res += cnt * facts[num - i - ];
    }
    return res;
}

vector<int> temp;
void decode(int n, int m) {
    temp.clear();
    ;
    int i, j, r, t;
    ; --t) {
        r = m / facts[t - ];
        m %= facts[t - ];
        ; i <= n; ++i) {
            )) {
                )break;
                --r;
            }
        }
        temp.push_back(i);
        buf |=  << i;
    }
}

];
int get() {
    vector<int> vec;
    int len = strlen(line);
    ; i < len; ++i) {
        ');
        );
    }
    ;
    , sz = vec.size(); i < sz; ++i) {
        )continue;
        ; j < i; ++j) {
            )continue;
            if(vec[j] > vec[i])++cnt;
        }
    }
    );
    else return encode(vec);
}

int findPos() {
    ; i < ; ++i))return i;
    ;
}
typedef struct Foo {
    int code;
    char step;
    Foo(int l, char s) {
        code = l;
        step = s;
    }
    Foo() {}
} Node;
];
, , -, };
queue<];
][];
Node pre[][];
bool bfs(int s[]) {
    ; i < ; ++i) {
        res[i].clear();
        while(!que[i].empty())que[i].pop();
        memset(vis[i], , sizeof(vis[i]));
        vis[i][s[i]] = true;
        ; j < ; ++j)pre[i][j].code = -;
        que[i].push(s[i]);
    }
    ;
    while(!que[k].empty()) {
        ].size();
        )k ^= ;//队列均衡优化

        int code = que[k].front();
        que[k].pop();
        ][code]) {
            ; i < ; ++i) {
                int now = code;
                int last = pre[i][now].code;
                ) {
                    res[i].push_back(pre[i][now].step);
                    now = last;
                    last = pre[i][last].code;
                }
                )reverse(res[i].begin(), res[i].end());
            }
            return true;
        }
        decode(, code);
        int pos = findPos();
        ; i < ; ++i) {
            int np = pos + dirs[i];
             || np > )continue;
            bool cond = false;
             || i == )cond = (np /  == pos / );
             || i == )cond = (np >=  && np <= );
            if(cond) {
                swap(temp[np], temp[pos]);
                int nv = encode(temp);
                if(!vis[k][nv]) {
                    )pre[k][nv] = Node(code, 'l');
                    )pre[k][nv] = Node(code, 'r');
                    )pre[k][nv] = Node(code, 'u');
                    )pre[k][nv] = Node(code, 'd');
                    que[k].push(nv);
                    vis[k][nv] = true;
                }
                swap(temp[np], temp[pos]);
            }
        }
        k ^= ;
    }
    return false;
}

void change(string& s) {
    , len = s.length(); i < len; ++i) {
        if(s[i] == 'l')s[i] = 'r';
        else if(s[i] == 'r')s[i] = 'l';
        else if(s[i] == 'u')s[i] = 'd';
        else if(s[i] == 'd')s[i] = 'u';
    }
    reverse(s.begin(), s.end());
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
#endif // ONLINE_JUDGE
    ios::sync_with_stdio(false);
    init();
    while(gets(line) != NULL) {
        int v = get();
        )cout << "unsolvable" << endl;
        )cout << endl;
        else {
            };
            if(bfs(s)) {
                change(res[]);
                cout << res[] << res[] << endl;
            } else cout << "unsolvable" << endl;
        }
    }
}

2、A*搜索。

#include<bits/stdc++.h>
using namespace std;
];
];
typedef struct Foo {
    int code;
    int pos9;
    double g, h;
    Foo(int c, int p, double _g, double _h) {
        code = c;
        pos9 = p;
        g = _g;
        h = _h;
    }
    Foo() {}
    /*这里写法决定时间的数量级:
        用注释的这种写法:耗时2700+ms;
        用没注释的这种写法,if括号里写成fabs(h - ano.h) < 1e-8,耗时1200+ms;
        现在这种写法:耗时800+ms;;
    */
    bool operator < (const Foo ano) const {
//        if(fabs(f - ano.f) < 1e-8)return h > ano.h;
//        else return f > ano.f;
        if(h == ano.h)return g > ano.g;
        else return h > ano.h;
    }
} Node;

void init0() {
    facts[] = facts[] = ;
    ; i < ; ++i)facts[i] = facts[i - ] * i;
}

int encode(string& seq) {
    , len = seq.length(), i, j, cnt;
    ; i < len; ++i) {
        cnt = (seq[i] - ');
        ; j < i; ++j)if(seq[j] < seq[i])--cnt;
        res += cnt * facts[len - i - ];
    }
    return res;
}

string decode(int code) {
    ;
    string res;
    ; t > ; --t) {
        r = code / facts[t - ];
        code %= facts[t - ];
        ; i <= ; ++i) {
            )) {
                )break;
                else --r;
            }
        }
        res.push_back(i + ');
        board |=  << i;
    }
    return res;
}

double distance(int src) {
    double res = 0.0;
    string seq = decode(src);
    int len = seq.length();
    int i, j, x0, y0, x1, y1, num;
    ; i < len; ++i) {
        num = seq[i] - ';
        x0 = (num - ) / , y0 = (num - ) % ;
        x1 = i / , y1 = i % ;
        res += abs(x0 - x1) + abs(y0 - y1);
    }
    return res;
}

int find_pos9(string& str) {
    int len = str.length(), i;
    ; i < len; ++i)')return i;
    ;
}

, , -, };
priority_queue<Node> que;
];
pair<];
string ans;

bool bfs(int s) {
    int i, j, k;
    int pos9, npos9, ncode;
    string seq;
    Node top_node;
    while(!que.empty())que.pop();
    memset(vis, , sizeof(vis));
    ; i < facts[]; ++i)pre[i].first = -;
    vis[s] = true;
    seq = decode(s);
    pos9 = find_pos9(seq);
    que.push(Node(s, pos9, , distance(s)));
    while(!que.empty()) {
        top_node = que.top();
        que.pop();
        ) {
            ans.clear();
            ; now = last, last = pre[last].first) {
                ans.push_back(pre[now].second);
            }
            reverse(ans.begin(), ans.end());
            return true;
        }
        seq = decode(top_node.code);
        pos9 = top_node.pos9;
        ; i < ; ++i) {
            npos9 = pos9 + dirs[i];
             || npos9 > )continue;
             || i == ) && npos9 /  != pos9 / )continue;
             || i == ) && (npos9 <  || npos9 > ))continue;
            swap(seq[npos9], seq[pos9]);
            ncode = encode(seq);
            if(!vis[ncode]) {
                pre[ncode].first = top_node.code;
                )pre[ncode].second = 'l';
                )pre[ncode].second = 'r';
                )pre[ncode].second = 'u';
                )pre[ncode].second = 'd';
                que.push(Node(ncode, npos9, top_node.g + , distance(ncode)));
                vis[ncode] = true;
            }
            swap(seq[npos9], seq[pos9]);
        }
    }
    return false;
}

int get_code(char str[]) {
    string temp;
    int len = strlen(str), i, j, cnt;
    ; i < len; ++i) {
        if(isdigit(str[i]))temp.push_back(str[i]);
        ');
    }
    cnt = ;
    len = temp.length();
    ; i < len; ++i) {
        ')continue;
        ; j < i; ++j) {
            ')continue;
            if(temp[j] > temp[i])++cnt;

        }
    }
    );
    else return encode(temp);
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
#endif // ONLINE_JUDGE
    ios::sync_with_stdio(false);
    init0();
    while(gets(input) != NULL) {
        int code = get_code(input);
        )cout << "unsolvable" << endl;
        )cout << endl;
        else cout << (bfs(code) ? ans : "unsolvable") << endl;
    }
    ;
}

3、纯C语言版A*算法。耗时:400+ms。其实priority_queue和stack等都是C++ STL。^_^

#include<bits/stdc++.h>
using namespace std;
];
];
typedef struct Foo {
    ];
    int code, pos9;
    double g, h;
    Foo(char s[], int c, int p, double _g, double _h) {
        strcpy(seq, s);
        code = c, pos9 = p;
        g = _g, h = _h;
    }
    Foo() {}
    bool operator < (const Foo ano) const {
        if(h == ano.h)return g > ano.g;
        else return h > ano.h;
    }
} Node;

void init0() {
    facts[] = facts[] = ;
    ; i < ; ++i)facts[i] = facts[i - ] * i;
}

int encode(const char seq[]) {
    , i, j, cnt, len = strlen(seq);
    ; i < len; ++i) {
        cnt = seq[i] - ';
        ; j < i; ++j)if(seq[j] < seq[i])--cnt;
        res += cnt * facts[len - i - ];
    }
    return res;
}

int find_pos9(const char str[]) {
    int len = strlen(str), i;
    ; i < len; ++i)')return i;
    ;
}

double dist(const char str[]) {
    int len = strlen(str), i, x0, y0, x1, y1, num;
    double res = 0.0;
    ; i < len; ++i) {
        num = str[i] - ';
        x0 = (num - ) / , y0 = (num - ) % ;
        x1 = i / , y1 = i % ;
        res += abs(x0 - x1) + abs(y0 - y1);
    }
    return res;
}

, , -, };
priority_queue<Node> que;
];
pair<];
stack<char> ans;
bool bfs(int s) {
    int i, j, k;
    Node node, new_node;
    while(!que.empty())que.pop();
    memset(vis, , sizeof(vis));
    ; i < facts[]; ++i)pre[i].first = -;
    vis[s] = true;
    que.push(Node(input, s, find_pos9(input), , dist(input)));
    while(!que.empty()) {
        node = que.top();
        que.pop();
        ) {
            while(!ans.empty())ans.pop();
            ].first, now = ; last != -; now = last, last = pre[last].first)
                ans.push(pre[now].second);
            return true;
        }
        ; i < ; ++i) {
            new_node = node;
            new_node.pos9 += dirs[i];
             || new_node.pos9 > )continue;
             || i == ) && (new_node.pos9 /  != node.pos9 / ))continue;
            swap(new_node.seq[new_node.pos9], new_node.seq[node.pos9]);
            new_node.code = encode(new_node.seq);
            if(!vis[new_node.code]) {
                ++new_node.g;
                new_node.h = dist(new_node.seq);
                que.push(new_node);
                vis[new_node.code] = true;
                pre[new_node.code].first = node.code;
                )pre[new_node.code].second = 'l';
                )pre[new_node.code].second = 'r';
                )pre[new_node.code].second = 'u';
                )pre[new_node.code].second = 'd';
            }
        }
    }
    return false;
}

int get_code(char str[]) {
    ];
    int i, j, len = strlen(str);
    , j = ; i < len; ++i) {
        if(isdigit(str[i]))temp[j++] = str[i];
        ';
    }
    temp[j++] = '\0';

    memset(input, '\0', sizeof(input));
    strcpy(input, temp);

    ;
    len = j - ;
    ; i < len; ++i) {
        ')continue;
        ; j < i; ++j) {
            ')continue;
            if(temp[j] < temp[i])++cnt;
        }
    }
    );
    else return encode(temp);
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
#endif
    init0();
    while(gets(input) != NULL) {
        int code = get_code(input);
        )printf("unsolvable\n");
        )putchar('\n');
        else {
            if(bfs(code)) {
                for(; !ans.empty(); ans.pop())putchar(ans.top());
                putchar('\n');
            } else printf("unsolvable\n");
        }
    }
    ;
}

六、A*算法确实是厉害。估值函数写得好可以很快;写不好,效果就会很差,甚至退化成普通的BFS。

HDU 1043 八数码问题的多种解法的更多相关文章

  1. Eight POJ - 1077 HDU - 1043 八数码

    Eight POJ - 1077 HDU - 1043 八数码问题.用hash(康托展开)判重 bfs(TLE) #include<cstdio> #include<iostream ...

  2. HDU 1043 八数码(A*搜索)

    在学习八数码A*搜索问题的时候须要知道下面几个点: Hash:利用康托展开进行hash 康托展开主要就是依据一个序列求这个序列是第几大的序列. A*搜索:这里的启示函数就用两点之间的曼哈顿距离进行计算 ...

  3. HDU 1043 八数码(八境界)

    看了这篇博客的讲解,挺不错的.http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html 判断无解的情况(写完七种境界才发现有直接判 ...

  4. HDU 1043 八数码 Eight A*算法

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  5. Eight hdu 1043 八数码问题 双搜

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  6. hdu 1043 八数码问题

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  7. hdu 1043 Eight 经典八数码问题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 The 15-puzzle has been around for over 100 years ...

  8. HDU 1043 Eight 八数码问题 A*算法(经典问题)

    HDU 1043 Eight 八数码问题(经典问题) 题意 经典问题,就不再进行解释了. 这里主要是给你一个状态,然后要你求其到达\(1,2,3,4,5,6,7,8,x\)的转移路径. 解题思路 这里 ...

  9. HDU 1043 Eight(八数码)

    HDU 1043 Eight(八数码) 00 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)   Problem Descr ...

随机推荐

  1. 面向对象之php多态

    php是面向对象的脚本语言,而我们都知道,面向对象的语言具有三大特性:封装,继承,多态(接口的多种不同的实现方式即为多态). 封装是类的构建过程,php具有.php也具有继承的特性.唯独这个多态,ph ...

  2. Android -- service的开启方式, start开启和绑定开启服务,调用服务的的方法, aidl调用远程服务

    1. 概述 bindService() 绑定服务  可以得到服务的代理人对象,间接调用服务里面的方法. 绑定服务: 间接调用服务里面的方法.           如果调用者activity被销毁了, ...

  3. install ros-indigo-laser-geometry

    -- Using these message generators: gencpp;genlisp;genpy CMake Warning at /opt/ros/indigo/share/catki ...

  4. Linux 常用环境搭建

    已有环境 python 2.6.6 jdk 1.7 —tomcat— —jenkins— —jq— —Python 2.7— —pip— —PIL— —Android SDK— —yum or apt ...

  5. 对于应用之间的调用,如何选择rpc还是mq?

    两个系统之间的调用,是选择rpc呢还是mq,说一下你们系统的选择吧 比如rpc可以是简单的spring httpinvoker,但是前提是都是java应用而且都是用spring framework,可 ...

  6. Python yield 用法

    一.环境 python 3.6 二.yield 说明 yield 是一个生成器,可以用于迭代.也是一个类似 return 的关键字,迭代一次遇到yield时就返回yield后面(右边)的值. 重点是: ...

  7. OKR 说明

    转载来源: http://www.jianshu.com/p/ce1141084427 一.什么是OKR? OKR的全称是“Objectives and Key Results”,翻译过来就是“目标和 ...

  8. 2018-2019-2 网络对抗技术 20165332 Exp2 后门原理与实践

    2018-2019-2 网络对抗技术 20165332 Exp2 后门原理与实践 - 实验内容 任务一:使用netcat获取主机操作Shell,cron启动 任务二:使用socat获取主机操作Shel ...

  9. supervisor进程管理工具

    Supervisor 一个python写的进程管理工具,用来启动.关闭.重启进程,可以同时控制多个进程. 安装: pip install supervisor 配置: 通过配置文件来满足自己的需求 配 ...

  10. vue 子组件把数据传递给父组件

    <div id="app"> <child v-on:drop='parent'></child> //这里v-on:drop="pa ...