码迷,mamicode.com
首页 > 其他好文 > 详细

康托展开

时间:2017-05-02 16:44:39      阅读:150      评论:0      收藏:0      [点我收藏+]

标签:数字   ext   mat   十进制   class   microsoft   fine   logs   span   

技术分享

例题

1 ~ n 的排列是有序的。如 (1, 2, 3) 按从小到大排列一共有 6 个:

123,132,213,231,312,321,

每个序列分别可以代表数字:1, 2, 3, 4, 5, 6

现在已知 n 和一个共 n 个数的排列,请问它对应的十进制数是多少。

解析

例如 n = 4,排列 2,3,1,4,我们就可以用康托展开来计算:

  • 比 2 小的数有 1,一共有 1 个;
  • 比 3 小的数有 1,2,其中 2 已经在前面出现过了,所以一共有 1 个;
  • 比 1 小的数没有,有 0 个;
  • 比 4 小的数有 1,2,3,其中 1,2,3 都已经在前面出现过了,所以一共有 0 个。

     1×3!+1×2!+0×1!+0×0!=8

 

也就是说,排列 2,3,1,4 是第 8 小的(从 00 开始),其对应的十进制数是 9。

 

技术分享

技术分享

这题感觉和康托展开没有关系丫。。sizeof(string|int)的值都是4。用了int真的会减少空间开销吗?

刚开始直接用string去bfs空间超,就把字符串转成了康托值int,最后发现是个小函数写错了。。。

#include<iostream>
#include<stdio.h>
#include<vector>
#include<queue>
#include<algorithm>
#include<memory.h>
#include<string.h>
#include<cmath>
#include<map>
#include<set>
#define INF 0x3f3f3f3f
#define PII pair<int,int>
#define MOD 1000000007
using namespace std;
struct state
{
    int now;
    string path;
    state(int nn,string pp)
    {
        now=nn;
        path=pp;
    }
};
string a,b;
int a_kangtuo,b_kangtuo;
string ans="";
int vis[40320];
int sup[9]={1,1,2,6,24,120,720,5040,40320};
string transform_A(string s)
{
    string n="";
    for(int i=s.length()-1;i>=0;i--)
        n+=s[i];
    return n;
}
string transform_B(string s)
{
    string n="";
    n+=s[3];
    n+=s[0];
    n+=s[1];
    n+=s[2];
    n+=s[5];
    n+=s[6];
    n+=s[7];
    n+=s[4];
    return n;
}
string transform_C(string s)
{
    string n=s;
    n[1]=s[6];
    n[2]=s[1];
    n[5]=s[2];
    n[6]=s[5];
    return n;
}

int kangtuo(string s)
{
    int ans=0;
    for(int i=0;i<s.length();i++)
    {
        int temp=0;
        for(int j=i+1;j<s.length();j++)
        {
            if(s[i]>s[j]) temp++;
        }
        ans+=temp*sup[s.length()-1-i];
    }
    return ans;
}
char cs[8]={1,2,3,4,5,6,7,8};
string mapping[40320];
void bfs(state s)
{
    int time=0;
    queue<state> q;
    q.push(s);
    while(!q.empty())
    {
        state ss=q.front();
        q.pop();
        if(ss.now==b_kangtuo)
        {
            ans=ss.path;
            break;
        }
        int t1=kangtuo(transform_A(mapping[ss.now]));
        int t2=kangtuo(transform_B(mapping[ss.now]));
        int t3=kangtuo(transform_C(mapping[ss.now]));
        if(!vis[t1])
        {
            q.push(state(t1,ss.path+"A"));
            vis[t1]=1;
        }
        if(!vis[t2])
        {
            q.push(state(t2,ss.path+"B"));
            vis[t2]=1;
        }
        if(!vis[t3])
        {
            q.push(state(t3,ss.path+"C"));
            vis[t3]=1;
        }
    }
}

int main()
{
    cin>>a;
    cin>>b;
    a_kangtuo=kangtuo(a);
    b_kangtuo=kangtuo(b);
    memset(vis,0,sizeof(vis));
    int i=0;
    do{
        string t(&cs[0],&cs[strlen(cs)]);
        mapping[i++]=t;
    }while(next_permutation(cs,cs+8));
    bfs(state(a_kangtuo,""));
    cout<<ans<<endl;
    return 0;
}

 

康托展开

标签:数字   ext   mat   十进制   class   microsoft   fine   logs   span   

原文地址:http://www.cnblogs.com/wangkaipeng/p/6796710.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!