• Magic Squares USACO 3.2 (康托展开)


    容易想到bfs,然后是根据重复剪枝,问题是如何判重复,若把每次访问过的字符串看成数作为index,最大有87654321,

    而实际只有8!阶乘个数,大致40000多点。

    这里要用到

    康托展开

    应用实例

    {1,2,3,4,...,n}表示1,2,3,...,n的排列如 {1,2,3} 按从小到大排列一共6个。123 132 213 231 312 321 。
    代表的数字 1 2 3 4 5 6 也就是把10进制数与一个排列对应起来。
    他们间的对应关系可由康托展开来找到。
    如我想知道321是{1,2,3}中第几个小的数可以这样考虑 :
    第一位是3,当第一位的数小于3时,那排列数小于321 如 123、 213 ,小于3的数有1、2 。所以有2*2!个。再看小于第二位2的:小于2的数只有一个就是1 ,所以有1*1!=1 所以小于321的{1,2,3}排列数有2*2!+1*1!=5个。所以321是第6个小的数。 2*2!+1*1!+0*0!就是康托展开。
    再举个例子:1324是{1,2,3,4}排列数中第几个大的数:第一位是1小于1的数没有,是0个 0*3! 第二位是3小于3的数有1和2,但1已经在第一位了,所以只有一个数2 1*2! 。第三位是2小于2的数是1,但1在第一位,所以有0个数 0*1! ,所以比1324小的排列有0*3!+1*2!+0*1!=2个,1324是第三个小数。
     
    所以每个数可以展开为该数在整个排列集合里第几小来判重
     
     1 int CantorHash(string & str)
     2 {
     3     int hash_index=0;
     4     for(int i=0;i<str.length();i++)
     5     {
     6         int temp=0;
     7         for(int j=i+1;j<str.length();j++)
     8         {
     9     
    10             if(str[i]>str[j])
    11                 temp++;
    12         }
    13         hash_index+=temp*FRAC[7-i];
    14     }
    15     return hash_index+1;
    16 }

    最后+1是因为hash_index表示比当前数小的数的个数。

    /*
    
    ID: hubiao cave
    
    PROG: msquare
    
    LANG: C++
    
    */
    
    
    
    
    #include<iostream>
    
    #include<fstream>
    
    #include<string>
    #include<deque>
    
    using namespace std;
    
    
    void Afunc(string&);
    void Bfunc(string&);
    void Cfunc(string&);
    
    bool gVisted[44000];
    const int FRAC[8]= {1, 1, 2, 6, 24, 120, 720, 5040};
    
    int CantorHash(string & str)
    {
        int hash_index=0;
        for(int i=0;i<str.length();i++)
        {
            int temp=0;
            for(int j=i+1;j<str.length();j++)
            {
        
                if(str[i]>str[j])
                    temp++;
            }
            hash_index+=temp*FRAC[7-i];
        }
        return hash_index+1;
    }
    
    int main()
    
    {
    
    
        ifstream fin("msquare.in");
    
        ofstream fout("msquare.out");
        
        typedef deque<pair<string,string> >Queues;
        Queues str_queue;
        string goal_string;
        string original_string="12345678";
        string temp_string;
        char ch;
        while(fin>>ch)
        {
            goal_string+=ch;
        }
    
        str_queue.push_back(make_pair(original_string,""));
        while(str_queue.size()!=0)
        {
            pair<string,string> p=str_queue.front();
            str_queue.pop_front();
            temp_string=p.first;
            int hashindex=CantorHash(p.first);
            if(gVisted[hashindex])
                continue;
            else
            {
                gVisted[hashindex]=true;
            }
    
            if(p.first==goal_string)
            {
                fout<<p.second.size()<<endl;
                fout<<p.second<<endl;
                return 0;
            }
            else
            {
                string temp=temp_string;
                Afunc(temp);
                str_queue.push_back(make_pair(temp,p.second+'A'));
        
                temp=temp_string;
                Bfunc(temp);
                str_queue.push_back(make_pair(temp,p.second+'B'));
    
    
                temp=temp_string;
                Cfunc(temp);
                str_queue.push_back(make_pair(temp,p.second+'C'));
        
    
            }
        }
        return 0;
    
    
    }
    void Afunc(string& pstr)
    {
        for(int i=0;i<4;i++)
        {
            char ch=pstr[i];
            pstr[i]=pstr[7-i];
            pstr[7-i]=ch;
        }
    }
    
    void Bfunc(string& pstr)
    {
        char ch1=pstr[3],ch2=pstr[4];
        pstr[3]=pstr[2],pstr[4]=pstr[5];
        pstr[2]=pstr[1],pstr[5]=pstr[6];
        pstr[1]=pstr[0],pstr[6]=pstr[7];
        pstr[0]=ch1,pstr[7]=ch2;
    }
    
    void Cfunc(string& pstr)
    {
        char ch=pstr[2];
        pstr[2]=pstr[1];
        pstr[1]=pstr[6];
        pstr[6]=pstr[5];
        pstr[5]=ch;
    }
  • 相关阅读:
    Mybatis中selectKey源码分析
    Mybatis 基于注解Mapper源码分析
    MyBatis的二级缓存以及装饰器模式运用
    ConcurrentSkipListMap源码分析
    CopyOnWriteArrayList源码分析
    InnoDB 单列索引与多列索引
    Java 线程池源码分析
    JDK8 ReentrantReadWriteLock源码分析
    关于lombok的坑
    on duplicate key update 的用法说明(解决批量操作数据,有就更新,没有就新增)mybatis批量操作数据更新和添加
  • 原文地址:https://www.cnblogs.com/cavehubiao/p/3358439.html
Copyright © 2020-2023  润新知