• 转换地图 (康托展开+预处理+BFS)


    Problem Description

    在小白成功的通过了第一轮面试后,他来到了第二轮面试。面试的题目有点难度了,为了考核你的思维能量,面试官给你一副(2x4)的初态地图,然后在给你一副(2x4)的终态地图。每一幅地图都是有数字1~8表示,给你的地图的信息是一串序列,然后根据这序列,从地图的左上角开始,按照顺时针排列。 比如地图信息为12345678,则表示地图:

    1 2 3 4
    8 7 6 5

    对于这地图有三种具体操作方式:

    A: 上下两行互换,如上图可变换为状态87654321
    B: 每行同时循环右移一格,如上图可变换为41236785
    C: 中间4个方块顺时针旋转一格,如上图可变换为17245368

    根据所给的初状地图和终态地图,请给出完成转化的最少的变换步骤,若有多种变换方案则取字典序最小的那种。

    Input

    每组测试数据包括两行,分别代表地图信息的初态与终态。

    Output

    对于每次测试案例,输出需要符合要求的变换步骤。

    SampleInput

    12345678
    17245368
    12345678
    82754631

    SampleOutput

    C
    AC

    最开始预处理了一下直接搜,本地爆炸。
    然后想到了用康托展开打个表,然后。。。就AC了。
    这里讲一下康托展开算法
      X = An * (n-1)! + An-1 * (n-2)! + ... + A1 * 0!;
    康拓展开就是求一个数字字符串在其全排列中的位置。
    例如231这个数,全排列为123 132 213 231 312 321
    所以231排在第4位,那么康托展开算法是如何求的呢。
    例如求231的康托展开,从头至尾依次判断:
    1. 第一位数2,比2小的有一个,有1*2!
    2. 第二位数3,比3小的有两个,但2已经出现,有1*1!
    3. 第三位数1,有0*0!

    累加起来就是2 + 1 = 3,表示比231小的有3个,所以231排在第4位。

    代码实现的话就是:

     1 int fac[] = {1,1,2,6,24,120,720,5040,40320};  //i的阶乘
     2 int kangtuo(int n,char a[]){  //n表示1~n个数,a数组表示数字
     3     int i,j,t,res = 0;
     4     for(i = 0; i < n; i++){
     5         t = 0;
     6         for(j = i+1; j < n; j++)
     7             if(a[i] > a[j])
     8                 t++;
     9         res += t*fac[n-i-1];
    10     }
    11     return sum + 1;
    12 }

    知道了康托展开后,就可以打表做了,值得一提的是这道题的预处理。因为题目输入两组字符串分别表示初始状态和结束状态,而我们打表是从12345678到各个状态的值,所以预处理我们把输入的初状态转成12345678,末状态也执行相应转换就可以了;

    代码:

      1 #include <iostream>
      2 #include <string>
      3 #include <cstdio>
      4 #include <cstdlib>
      5 #include <sstream>
      6 #include <iomanip>
      7 #include <map>
      8 #include <stack>
      9 #include <deque>
     10 #include <queue>
     11 #include <vector>
     12 #include <set>
     13 #include <list>
     14 #include <cstring>
     15 #include <cctype>
     16 #include <algorithm>
     17 #include <iterator>
     18 #include <cmath>
     19 #include <bitset>
     20 #include <ctime>
     21 #include <fstream>
     22 #include <limits.h>
     23 #include <numeric>
     24 
     25 using namespace std;
     26 
     27 #define F first
     28 #define S second
     29 #define mian main
     30 #define ture true
     31 
     32 #define MAXN 1000000+5
     33 #define MOD 1000000007
     34 #define PI (acos(-1.0))
     35 #define EPS 1e-6
     36 #define MMT(s) memset(s, 0, sizeof s)
     37 typedef unsigned long long ull;
     38 typedef long long ll;
     39 typedef double db;
     40 typedef long double ldb;
     41 typedef stringstream sstm;
     42 const int INF = 0x3f3f3f3f;
     43 
     44 struct node{
     45     string str,step;
     46 };
     47 
     48 bool vis[40320+1];
     49 int  pos[10],fac[] = {1,1,2,6,24,120,720,5040,40320};
     50 string ans[41000];
     51 
     52 
     53 int fun(string a){
     54     int i,j,t,sum = 0;
     55     for(i = 0; i < 8; ++i){
     56         t = 0;
     57         for(j = i+1; j < 8; ++j)
     58             if(a[i] > a[j])
     59                 ++t;
     60         sum += t*fac[8-i-1];
     61     }
     62     return sum+1;
     63 }
     64 
     65 void ma(string &s){
     66     for(int i = 0; i < 4; ++i)
     67         swap(s[i],s[i+4]);
     68 }
     69 
     70 string mb(string s){
     71     string temp = s;
     72     for(int i = 0; i < 8; ++i){
     73         if(i==0 || i==4)
     74             temp[i]=s[i+3];
     75         else
     76             temp[i]=s[i-1];
     77     }
     78     return temp;
     79 }
     80 
     81 void mc(string &s){
     82     swap(s[1],s[2]);
     83     swap(s[5],s[6]);
     84     swap(s[1],s[6]);
     85 }
     86 
     87 void bfs( string s ){
     88     MMT(vis);
     89     queue<node>q;
     90     node pre,nxt;
     91 
     92     pre.str = s;
     93     pre.step = "";
     94     vis[fun(s)] = 1;
     95     ans[fun(s)] = pre.step;
     96     q.push(pre);
     97 
     98     while(!q.empty()){
     99         pre = q.front();
    100         q.pop();
    101 
    102         nxt = pre;
    103         ma(nxt.str);
    104         if(!vis[fun(nxt.str)]){
    105             nxt.step += "A";
    106             vis[fun(nxt.str)] = 1;
    107             ans[fun(nxt.str)] = nxt.step;
    108             q.push(nxt);
    109         }
    110 
    111         nxt.str = mb(pre.str);
    112         if(!vis[fun(nxt.str)]){
    113             nxt.step = pre.step + "B";
    114             vis[fun(nxt.str)] = 1;
    115             ans[fun(nxt.str)] = nxt.step;
    116             q.push(nxt);
    117         }
    118 
    119         nxt = pre;
    120         mc(nxt.str);
    121         if(!vis[fun(nxt.str)]){
    122             nxt.step += "C";
    123             vis[fun(nxt.str)] = 1;
    124             ans[fun(nxt.str)] = nxt.step;
    125             q.push(nxt);
    126         }
    127     }
    128 }
    129 
    130 int main(){
    131     ios_base::sync_with_stdio(false);
    132     cout.tie(0);
    133     cin.tie(0);
    134     string s1,s2;
    135     int k;
    136     bfs("12345678");
    137     //12345678
    138     //17245368
    139     //12345678
    140     //82754631
    141     while(cin>>s1>>s2){
    142         swap(s1[4],s1[7]);
    143         swap(s1[5],s1[6]);
    144         swap(s2[4],s2[7]);
    145         swap(s2[5],s2[6]);
    146         for(int i = 0; i < 8; i++)
    147             pos[s1[i]-'0'] = i+1;
    148         for(int i = 0; i < 8; i++)
    149             s2[i] = pos[s2[i]-'0'];
    150         k = fun(s2);
    151         cout<<ans[k]<<endl;
    152     }
    153     return 0;
    154 }

    其实康托展开也可以求逆运算,具体思想以及代码实现这里就不讲了=7=

  • 相关阅读:
    linux下文件的复制、移动与删除
    Hbase万亿级存储性能优化总结-配置
    hbase 读写和优化
    hive数据倾斜定位及处理
    flink初识及安装flink standalone集群
    【Linux】用less查看日志文件
    sqoop的详细使用及原理
    HBase删除数据的原理
    hbase数据加盐(Salting)存储与协处理器查询数据的方法
    Hbase内存磁盘大致关系
  • 原文地址:https://www.cnblogs.com/xenny/p/9382070.html
Copyright © 2020-2023  润新知