不会康拓的同学们看这里!!
表示作者的朋友都太厉害了,经过为时30分钟的思考就想出了康拓展开(他在此之前都还不了解康拓@wasa855)
但作者是一个不会康拓的蒟蒻,所以怎么办呢?
本题十分明显,如果用8进制的权值记录,进行判重,有百分之80的几率MLE(可能更高,作者没有尝试过)。
所以作者就想出了一种神奇的方法,而应用的知识,仅仅是:
二分查找
下面就进入正题,如何二分呢?
当然是打一张巨表了
贴代码:
for(int i=1;i<=8;++i) { s[l].a[i]=i; } for(int i=1;i<=40320;++i) { for(int j=1;j<=8;++j) { f[i].a[j]=s[l].a[j]; } next_permutation(s[l].a+1,s[l].a+1+8); }
传说中的巨表!!!
眼尖的同学可能发现了,next_permutation是什么呢?
这其实是一个神奇的全排列函数,可以帮你求下一个排列,是C++的STL库< algorithm >中的函数。(请大家打开P1088,用这个函数水过)
再进行二分:
int big_small(int a[],int b[]) { for(int i=1;i<=8;++i) { if(a[i]>b[i]) return 1; if(a[i]<b[i]) return -1; } return 0; } bool used(int a[]) { int l=1,r=40320,mid,t; while(l<=r) { mid=(l+r)/2; t=big_small(f[mid].a,a); if(t>0) r=mid-1; if(t<0) l=mid+1; if(t==0) break; } if(f[mid].n==false) { f[mid].n=true; return false; } else return true; }
以上就是判重的思路,然而最重要的,其实是广搜(不要告诉我你不会!!!)
大佬wasa855说,深搜和广搜就是傻子和聪明人走迷宫的区别。
深搜就是傻子一个劲的往里冲,碰到不能走或者边界(边界好像也不能走),就往回走(回溯)广搜呢,就是聪明人,他们把能走的都先看一遍,再往下走。
不过傻子和聪明人各有所长,大家要因题而异。(不要因为我说深搜是傻子就不用)
最后贴代码,祝大家题题AC:
#include#include using namespace std; struct Squares { int a[9]; int n; char p[100]; }s[40321]; struct squares { int a[9]; bool n; }f[40321]; int ans[9]; int l=0,r=1; int t1,t2; bool cmp(int a[]) { for(int i=1;i<=8;++i) { if(a[i]!=ans[i]) return false; } return true; } int big_small(int a[],int b[]) { for(int i=1;i<=8;++i) { if(a[i]>b[i]) return 1; if(a[i]<b[i]) return -1; } return 0; } bool used(int a[]) { int l=1,r=40320,mid,t; while(l<=r) { mid=(l+r)/2; t=big_small(f[mid].a,a); if(t>0) r=mid-1; if(t<0) l=mid+1; if(t==0) break; } if(f[mid].n==false) { f[mid].n=true; return false; } else return true; } void A() { s[r]=s[l]; for(int i=1;i<=4;++i) { t1=s[r].a[i]; s[r].a[i]=s[r].a[8-i+1]; s[r].a[8-i+1]=t1; } if(used(s[r].a)==true) { return ; } s[r].p[s[r].n]='A'; ++s[r].n; ++r; } void B() { s[r]=s[l]; t1=s[r].a[4]; t2=s[r].a[5]; for(int i=4;i>=2;--i) { s[r].a[i]=s[r].a[i-1]; s[r].a[8-i+1]=s[r].a[8-i+2]; } s[r].a[1]=t1; s[r].a[8]=t2; if(used(s[r].a)==true) { return ; } s[r].p[s[r].n]='B'; ++s[r].n; ++r; } void C() { s[r]=s[l]; t1=s[r].a[2]; s[r].a[2]=s[r].a[7]; s[r].a[7]=s[r].a[6]; s[r].a[6]=s[r].a[3]; s[r].a[3]=t1; if(used(s[r].a)==true) { return ; } s[r].p[s[r].n]='C'; ++s[r].n; ++r; } int main() { for(int i=1;i<=8;++i) { scanf("%d",&ans[i]); } f[1].n==true; for(int i=1;i<=8;++i) { s[l].a[i]=i; } for(int i=1;i<=40320;++i) { for(int j=1;j<=8;++j) { f[i].a[j]=s[l].a[j]; } next_permutation(s[l].a+1,s[l].a+1+8); } for(int i=1;i<=8;++i) { s[l].a[i]=i; } while(1) { if(cmp(s[l].a)==true) break; A(); B(); C(); ++l; } printf("%d",s[l].n); for(int i=0;i i) { if(i%60==0) printf("\n"); printf("%c",s[l].p[i]); } }
不知是数据太水还是正解,反正AC!!!
2018-06-12