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