hdu 1430 魔板

刚开始不知道有康托展开,一筹莫展,查了一下大神题解。看到说要用康托展开,遂跑去学。
康托展开: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,要继续加油!

你可能感兴趣的:(bfs,康托展开)