题意:
旋转A,B,C,D,一并带着相邻的四个数字旋转。
给定初始状态,求在给定次数下,能否到达如figure(a)的状态。
输入:十位字符串,第一位为给定次数,后九位为初始状态。
提交次数:3次(然鹅洛谷上的remotejudge一直CE)
错误:mxd初值设成了1,qwq
题解:
思路:搜索,IDA*
估价函数$h()$:每个数到应到位置的曼哈顿距离$\frac {\sum dis[i]}{4}$
正确性:每次旋转至多将这个值减少$4$
代码:
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #define R register int using namespace std; #define ull unsigned long long #define ll long long #define pause (for(R i=1;i<=10000000000;++i)) const int N=10; const int p[4]={1,2,4,5}; char s[N]; const int d[N][2]={ {0,0}, {1,1}, {1,2}, {1,3}, {2,1}, {2,2}, {2,3}, {3,1}, {3,2}, {3,3} }; int mp[N],mxd; inline void rot(int* a,int d) { memmove(a+d+1,a+1,sizeof(int)*4); if(d==1) a[1]=a[5],a[5]=0; if(d==-1) a[4]=a[0],a[0]=0; } inline void change(int pos,int d) { R a[6]; a[1]=mp[pos],a[2]=mp[pos+1],a[3]=mp[pos+4],a[4]=mp[pos+3]; rot(a,d); mp[pos]=a[1],mp[pos+1]=a[2],mp[pos+4]=a[3],mp[pos+3]=a[4]; } inline int h() { R ret=0; for(R i=1;i<=9;++i) { ret+=abs(((i-1)/3+1)-d[mp[i]][0])+abs((i-1)%3+1-d[mp[i]][1]); } return (ret+3)/4; } inline bool dfs(int s,int lstp,int lstd) { if(h()+s>mxd) return false; if(!h()) return true; R tmp[10]; memcpy(tmp,mp,sizeof(mp)); for(R i=0;i<=3;++i) for(R j=-1;j<=1;j+=2) if(!(i==lstp&&j==-lstd)) { change(p[i],j); if(dfs(s+1,i,j)) return true; memcpy(mp,tmp,sizeof(mp)); } return false; } signed main() { R T=0,Lim; while(1) { register bool flg=true; scanf("%s",s); Lim=s[0]^48; for(R i=1;i<=9;++i) mp[i]=s[i]^48,flg&=(s[i]==48); if(flg) break; for(mxd=0;mxd<=Lim&&!dfs(0,-1,0);++mxd) ; printf("%d. %d\n",++T,mxd<=Lim?mxd:-1); } }
2019.07.13