【cdoj 1380】 Xiper的奇妙历险(3) bfs+逆向思维 有质量的bfs

来源:互联网 发布:域名第四级地址 编辑:程序博客网 时间:2024/05/16 16:00

10000个操作绝对会T所以我们想到打表,但是表太大装不下,没事,既然只有30多万种情况我们反着来,从答案开始逆向bfs就好了,与处理出答案

居然忘了看拓展开了也是郁闷

X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! ,其中a[i]为当前未出现的元素中是排在第几个(从0开始)。这就是康托展开。

#include<cstdio>#include<cstring>#include<iostream>#include<queue>using namespace std;int T,tim;int vis[5000000];int ji[15];int biao[5000000];typedef pair<int,int>pii;queue<pii>q;const int dx[]={1,-1,0,0};const int dy[]={0,0,1,-1};int vv[12];int tt[13];int kantor(int x){memset(vv,0,sizeof(vv));int cnt=0,ans=0,op;*tt=9;while(x){tt[(*tt)--]=x%10;x/=10;}for(int i=1;i<=9;i++){op=0;vv[tt[i]]=1;for(int j=1;j<=tt[i];j++){if(!vv[j])op++;}ans+=ji[9-i]*op;}return ans;}int change(int x,int y,int a,int b,int pos){int p=(x-1)*3+y,q=(a-1)*3+b;*tt=9,x=0;while(pos){tt[(*tt)--]=pos%10;pos/=10;}swap(tt[p],tt[q]);for(int i=1;i<=9;i++){x=x*10+tt[i];}return x;}pii get(int pos){*tt=9;while(pos){tt[(*tt)--]=pos%10;pos/=10;}for(int i=1;i<=9;i++){if(tt[i]==9){int x=(i-1)/3+1;int y=i-3*(x-1);return make_pair(x,y);}}}void bfs(){while(!q.empty() ){pii u=q.front() ;q.pop();int pos=u.first,step=u.second;biao[kantor(pos)]=step;pii now=get(pos);int x=now.first,y=now.second;int nx,ny,npos;for(int i=0;i<4;i++){nx=x+dx[i],ny=y+dy[i];if(nx<1||nx>3||ny<1||ny>3)continue;npos=change(x,y,nx,ny,pos);int z=kantor(npos);if(vis[z]==tim)continue;vis[z]=tim;q.push(make_pair(npos,step+1)); }}}char s[3];int main(){memset(biao,-1,sizeof(biao));tim++;ji[1]=1;for(int i=2;i<=10;i++)ji[i]=i*ji[i-1];int pos=0;vis[kantor(123456789)]=1;for(int i=1;i<=9;i++)pos=pos*10+i;q.push(make_pair(pos,0)); bfs();scanf("%d",&T);while(T--){int poos=0;for(int i=1;i<=9;i++){scanf("%s",s);poos=poos*10+ (s[0]=='x'?9:s[0]-'0');}printf("%d\n",biao[kantor(poos)]);}return 0;}/*92 3 61 5 47 8 9*/

1 0
原创粉丝点击