hdu 1430 魔板

来源:互联网 发布:java系统架构师 编辑:程序博客网 时间:2024/06/05 07:14

刚开始不知道有康托展开,一筹莫展,查了一下大神题解。看到说要用康托展开,遂跑去学。
康托展开:http://blog.csdn.net/zhongkeli/article/details/6966805
学完写爆搜,结果TLE。冥思苦想半天,发现所有的魔版初态其实都可以用“12346578”来替换。即s->e可以等量变换成ss->se。所以我们只用bfs遍历“12345678”经过A,B,C三种变化后的所有可能解,然后将每种解存储下来,就可以直接取了。
花了两个小时写了这个代码。贴上去发现也不对。

#include<iostream>#include<cstdio>#include<algorithm>#include<string>#include<queue>using namespace std;const int N=8;struct node{    string s;    string step;};string b,c;queue<node> q;node start;string a[50000];int compress(int k,string s){    int sum=0;    for(int i=k+1;i<N;i++)    {        if(s[i]<s[k]) sum++;    }    return sum;}int fac(int ans){    if(ans==7)        return 5040;    if(ans==6)        return 720;    if(ans==5)        return 120;    if(ans==4)        return 24;    if(ans==3)        return 6;    if(ans==2)        return 2;    if(ans==1)        return 1;    if(ans==0)        return 0;}int kt(string s){    int sum=0;    int ans=7;    for(int i=0;i<N;i++)    {        sum+=compress(i,s)*fac(ans);        ans--;    }    return sum;}string Fun(string ss,int n){    int l,r;    if(n==0)    {        l=7;        r=0;        while(l>r)        {            swap(ss[l],ss[r]);            l--;            r++;        }        return ss;    }    if(n==2)    {        swap(ss[6],ss[2]);        swap(ss[1],ss[2]);        swap(ss[6],ss[5]);        return ss;    }    if(n==1)    {        for(int i=3;i>0;i--)            swap(ss[i],ss[i-1]);        for(int i=4;i<7;i++)            swap(ss[i],ss[i+1]);        //cout<<ss<<endl;        return ss;    }}void bfs(){    while(!q.empty())    {        node hd=q.front(); q.pop();        node t=hd;        int num;        for(int i=0;i<3;i++)        {            t=hd;            t.step.push_back(i+'A');            //cout<<t.step<<endl;            string ss=hd.s;            ss=Fun(ss,i);  //用i+'A'方案对ss变形            //cout<<ss<<endl;            num=kt(ss);            if(!a[num].size()&&num!=0)            {                a[num]=t.step;                t.s=ss;                q.push(t);            }        }    }}void ys(){    int k=0;    int j=1;    string bb=b,cc=c;    while(j<=8)    {        for(int i=0;i<N;i++)        {            if(b[i]==j+'0')            {                //cout<<j<<endl;                bb[k++]=b[i];                cc[k-1]=c[i];                j++;            }            if(j==9)            {                //cout<<bb<<endl;                //cout<<cc<<endl;                b=bb;                c=cc;                return ;            }        }    }}int main(){    freopen("in.txt","r",stdin);    memset(a,NULL,sizeof(a));    start.s="12345678";    int num=kt(start.s);    cout<<num<<endl;    a[num]=start.step;    q.push(start);    bfs();    while(cin>>b)    {        getchar();        cin>>c;        ys();        //cout<<b<<endl;        //cout<<c<<endl;        //cout<<kt(c);        cout<<a[kt(c)]<<endl;    }    return 0;}

找了老半天,是子函数ys发生错误。原来是我对于替换理解错了。
比如:13467852->16347852应该转变为12345678->14235678。
而我却认为应该变为12345678->12635478。
将代码改成这样

#include<iostream>#include<cstdio>#include<algorithm>#include<string>#include<queue>using namespace std;const int Nstruct node{string s;string step;};ing b,c;queue<node> q;node start;string a[50000];int compress(int k,string s){    int sum=0;    for(int i=k+1;i<N;i++)    {        if(s[i]<s[k]) sum++;    }    return sum;}int fac(int ans){    if(ans==7)        return 5040;    if(ans==6)        return 720;    if(ans==5)        return 120;    if(ans==4)        return 24;    if(ans==3)        return 6;    if(ans==2)        return 2;    if(ans==1)        return 1;    if(ans==0)        return 0;}int kt(string s){    int sum=0;    int ans=7;    for(int i=0;i<N;i++)    {        sum+=compress(i,s)*fac(ans);        ans--;    }    return sum;}string Fun(string ss,int n){    int l,r;    if(n==0)    {        l=7;        r=0;        while(l>r)        {            swap(ss[l],ss[r]);            l--;            r++;        }        return ss;    }    if(n==2)    {        swap(ss[6],ss[2]);        swap(ss[1],ss[2]);        swap(ss[6],ss[5]);        return ss;    }    if(n==1)    {        for(int i=3;i>0;i--)            swap(ss[i],ss[i-1]);        for(int i=4;i<7;i++)            swap(ss[i],ss[i+1]);        //cout<<ss<<endl;        return ss;    }}void bfs(){    while(!q.empty())    {        node hd=q.front(); q.pop();        node t=hd;        int num;        for(int i=0;i<3;i++)        {            t=hd;            t.step.push_back(i+'A');            //cout<<t.step<<endl;            string ss=hd.s;            ss=Fun(ss,i);  //用i+'A'方案对ss变形            //cout<<ss<<endl;            num=kt(ss);            if(!a[num].size()&&num!=0)            {                a[num]=t.step;                t.s=ss;                q.push(t);            }        }    }}void ys(){    string bb=b;    string cc=c;    for(int i=0;i<N;i++)    {        bb[i]=i+'0'+1;        for(int j=0;j<N;j++)            if(c[j]==b[i])                cc[j]=i+'0'+1;    }    //cout<<bb<<endl;    //cout<<cc<<endl;    b=bb;    c=cc;}int main(){    //freopen("in.txt","r",stdin);    memset(a,NULL,sizeof(a));    start.s="12345678";    int num=kt(start.s);    a[num]=start.step;    q.push(start);    bfs();    while(cin>>b)    {        getchar();        cin>>c;        ys();        //cout<<b<<endl;        //cout<<c<<endl;        //cout<<kt(c);        cout<<a[kt(c)]<<endl;    }    return 0;}

发现这个代码其实是可以简化的,今天或者明天我将我自己简化后的代码贴上来。
优化后的代码:首先发现子函数fac可以写成一个数组,可以将结构体node改一下。
原来是这样

struct node{    string s;    string step;};

改成这样:

struct node{    string s;    int step;};

本来是要储存一个两个string类型的字符串,优化成只用储存一个。有优化了一下ys函数,从O(N^2)优化成O(N*2).

#include<iostream>#include<cstdio>#include<algorithm>#include<string>#include<queue>using namespace std;const int N=8;struct node{    string s;    int step;};string b,c;queue<node> q;node start;string a[50000];int compress(int k,string s){    int sum=0;    for(int i=k+1;i<N;i++)    {        if(s[i]<s[k]) sum++;    }    return sum;}int fac[]={0,1,2,6,24,120,720,5040};int kt(string s){    int sum=0;    int ans=7;    for(int i=0;i<N;i++)    {        sum+=compress(i,s)*fac[ans];        ans--;    }    return sum;}string Fun(string ss,int n){    int l,r;    if(n==0)    {        l=7;        r=0;        while(l>r)        {            swap(ss[l],ss[r]);            l--;            r++;        }        return ss;    }    if(n==2)    {        swap(ss[6],ss[2]);        swap(ss[1],ss[2]);        swap(ss[6],ss[5]);        return ss;    }    if(n==1)    {        for(int i=3;i>0;i--)            swap(ss[i],ss[i-1]);        for(int i=4;i<7;i++)            swap(ss[i],ss[i+1]);        return ss;    }}void bfs(){    while(!q.empty())    {        node hd=q.front(); q.pop();        node t=hd;        int num;        for(int i=0;i<3;i++)        {            t=hd;            string ss=hd.s;            ss=Fun(ss,i);  //用i+'A'方案对ss变形            num=kt(ss);            if(!a[num].size()&&num!=0)            {                a[num]=a[t.step];                a[num].push_back(i+'A');                t.step=num;                t.s=ss;                q.push(t);            }        }    }}void ys(){    char pos[10];    for(int i=0;i<N;i++)        pos[b[i]-'0']=i+1;    for(int i=0;i<N;i++)        c[i]=pos[c[i]-'0'];}int main(){    //freopen("in.txt","r",stdin);    memset(a,NULL,sizeof(a));    start.s="12345678";    start.step=0;    int num=kt(start.s);    a[num]="";    q.push(start);    bfs();    while(cin>>b)    {        getchar();        cin>>c;        ys();        cout<<a[kt(c)]<<endl;    }    return 0;}

很多大神可以将之优化成0MS,要继续加油!

0 0
原创粉丝点击