zoukankan      html  css  js  c++  java
  • CDOJ 485 UESTC 485 Game (八数码变形,映射,逆cantor展开)

    题意:八数码,但是转移的方式是转动,一共十二种,有多组询问,初态唯一,终态不唯一。

    题解:初态唯一,那么可以预处理出012345678的所有转移情况,然后将初态对012345678做一个映射,再枚举一下终态的所有情况,取最小值即可。

    学了逆cantor展开,cantor展开是一个变进制数,每位上是原序列对应位置上的逆序值。那么求逆时候,就先除最大的位权得到对应位置上的逆序值,根据逆序值可以知道它在剩下的序列中第几大,然后标记它,迭代。状态转移有点麻烦。

    #include<cstdio>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<set>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<queue>
    using namespace std;
    typedef long long ll;
    //#define local
    
    const int maxn = 362880;
    int d[maxn];
    int fac[9] = { 1,1,2,6,24,120,720,5040,40320};//,362880
    int St[9],Ed[9];
    
    int cantor(int *e) {
            int ret = 0;
            for(int i = 0; i < 9; i++) {
                int cnt = 0;
                for(int j = i+1; j < 9; j++)
                    if(e[j] < e[i]) cnt++;
                ret += fac[8-i] * cnt;
            }
            return ret;
    }
    
    void invCantor(int *a,int code)
    {
        bool vis[10] = {0};
        for(int i = 0; i < 9; i++){
            int t = code/fac[8-i];
            int j;
            for( j = 0; j < 9 ; j++){
                if(!vis[j]){
                    if(t == 0) break;
                    t--;
                }
            }
            a[i] = j; vis[j] = 1;
            code %= fac[8-i];
        }
    }
    
    int dir[12][9] = {
    {2,0,1,3,4,5,6,7,8},{0,1,2,5,3,4,6,7,8},{0,1,2,3,4,5,8,6,7},
    {1,2,0,3,4,5,6,7,8},{0,1,2,4,5,3,6,7,8},{0,1,2,3,4,5,7,8,6},
    {6,1,2,0,4,5,3,7,8},{0,7,2,3,1,5,6,4,8},{0,1,8,3,4,2,6,7,5},
    {3,1,2,6,4,5,0,7,8},{0,4,2,3,7,5,6,1,8},{0,1,5,3,4,8,6,7,2} };
    queue<int> q;
    
    void BfsPre()
    {
        memset(d,-1,sizeof(d) );
        d[0] = 0;
        q.push(0);
        while(q.size()){
            int u = q.front();q.pop();
            int tmp[9];
            invCantor(tmp,u);
            for(int i = 0; i < 12; i++){
                int tmp2[9];
                for(int j = 0; j < 9; j++){
                    tmp2[j] = tmp[dir[i][j]];
                }
                int v = cantor(tmp2);
                if(~d[v]) continue;
                d[v] = d[u]+1;
                q.push(v);
            }
        }
    }
    
    
    int query()
    {
        int mp[9];
        for(int i = 0; i < 9; i++) { mp[St[i]] = i; }
        bool appear[9] = {0};
        for(int i = 0; i < 9; i++){
           if(~Ed[i]) appear[Ed[i] = mp[Ed[i]]] = 1;
        }
        int vec[9],sz = 0;
        for(int i = 0; i < 9; i++) {
            if(!appear[i]) vec[sz++] = i;
        }
        if(sz == 9)  return 0;
        if(sz == 0) return d[cantor(Ed)];
    const int INF =  0x7fffffff;
        int ans = INF;
        int tmp[9];
         do{
            int j = 0;
            for(int i = 0; i < 9; i++){
                if(~Ed[i]) { tmp[i] = Ed[i]; }
                else { tmp[i] = vec[j++]; }
            }
            int Hash = cantor(tmp);
            if(~d[Hash]) ans = min(ans,d[Hash]);
        }while(next_permutation(vec,vec+sz));
        return ans!=INF? ans : -1;
    }
    
    
    int main()
    {
    #ifdef local
        freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
    #endif // local
        int T;
        BfsPre();
    
        scanf("%d",&T);
        for(int k = 1; k <= T; k++){
            printf("Case #%d: ",k);
            for(int i = 0; i < 9; i ++){
                scanf("%d",St+i);
                St[i]--;
            }
            getchar();
            char buf[15];
            for(int i = 0; i < 3; i++){
                gets(buf);
                for(int j = 0; j < 5; j+=2){
                    if('1'<=buf[j] && buf[j] <= '9'){
                        Ed[i*3+j/2] = buf[j] - '1';
                    }else Ed[i*3+j/2] = -1;
                }
            }
            int ans = query();
            if(~ans) printf("%d
    ",ans);
            else printf("No Solution!
    ");
        }
    
        return 0;
    }
  • 相关阅读:
    Nginx 使用 GeoIP 模块区分用户地区
    使用nginx转发tcp请求(解决访问内网的腾讯云redis)
    open file cache提升nginx性能
    使用 nginx-http-concat
    使用goaccess对Nginx日志简单分析
    Zookeeper系列一:Zookeeper基础命令操作
    k8s nginx应用-获取客户端访问真实IP
    mysql 备份数据库中的一张表
    ssh命令带密码
    Linux下grep显示前后几行信息
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4678879.html
Copyright © 2011-2022 走看看