求最少次数,一般就是bfs或者dfs或者数学公式,这题用bfs加上hash很好写。
因为比较懒,就用了string类型,于是多出char和string的转换,浪费了很多时间,1.416s才过。
写hash时不要忘记加绝对值
/* author:jxy lang:C/C++ university:China,Xidian University **If you need to reprint,please indicate the source** */ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <queue> #define INF 1E9 using namespace std; string t; bool prim[16]={0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0}; int vis[40321]; bool used[10]; const int fac[8]={5040,720,120,24,6,2,1,1}; string now,ne; inline int abs(int a){return a>0?a:-a;} int hash(string s) { memset(used,0,sizeof(used)); int hh=0,i,j,t; for(i=0;i<7;i++) { s[i]=abs(s[i]); t=0; used[s[i]]=1; for(j=1;j<s[i];j++) if(!used[j])t++; hh+=t*fac[i]; } return hh; } queue<string> q; char next[10]; int bfs() { while(!q.empty())q.pop(); q.push(now); vis[hash(now)]=1; int i,j,k,t,tt; while(!q.empty()&&!vis[0]) { now=q.front();q.pop(); next[8]=now[8]+1; for(i=0;i<8;i++) { for(j=0;j<8;j++) { if(now[i]*now[j]>0)continue; if(!prim[abs(now[i])+abs(now[j])])continue; for(k=t=0;t<8;t++) { if(t==i)continue; if(t==j) { tt=k; next[k++]=now[i]; } next[k++]=now[t]; } ne=next; t=hash(ne); if(!vis[t]) { vis[t]=ne[8]; q.push(ne); } swap(next[tt],next[tt+1]); ne=next; t=hash(ne); if(!vis[t]) { vis[t]=ne[8]; q.push(ne); } } } } return vis[0]-1; } char N[10]; int main() { int C=0,i,t; while(scanf("%d",&t)&&t) { N[0]=t; memset(vis,0,sizeof(vis)); for(i=1;i<8;i++) { scanf("%d",&t); N[i]=t; } N[8]=1; now=N; printf("Case %d: %d\n",++C,bfs()); } }