HDU 1043 Eight(反向BFS打表+康托展开)
2016-12-07 21:39
417 查看
原题链接:Here!
分析:求经过若干次四个操作 ' r ' , ' l ' , ' u ' , ' d ' 到状态1 2 3 4 5 6 7 8 x,输出操作顺序。因为最终状态一定,所以采用反向BFS打表,记录路径即可。
CODE:
分析:求经过若干次四个操作 ' r ' , ' l ' , ' u ' , ' d ' 到状态1 2 3 4 5 6 7 8 x,输出操作顺序。因为最终状态一定,所以采用反向BFS打表,记录路径即可。
CODE:
/* Note: 因为题目要求是任意状态求是否能到一个"完美状态",因为任意状态不确定性和完美状态的确定性,所以不妨 反向BFS+打表 抠脚 */ #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<string> #include<queue> using namespace std; #define test int fac[]={1,1,2,6,24,120,720,5040,40320,362880}; int Cantor(int *s,int n){ // 康托展开 int ans=0; for(int i=0;i<n;i++){ int tmp=0; for(int j=i+1;j<n;j++) if(s[i]>s[j]) tmp++; ans += tmp*fac[n-1-i]; } return ans; } void unCantor(int index,int *t,int n){ // 康托逆展开 index--; int i,j; int vis[10]={0}; for(i=0;i<n;i++){ int tmp=index/fac[n-1-i]; for(j=0;j<=tmp;j++) if(vis[j]) tmp++; t[i]=tmp+1; vis[tmp]=1; index%=fac[n-1-i]; } } const int maxn = 362880; // 9! = 362880 bool can[maxn]; // 记录状态是否出现 char ans[maxn][42]; // 打个表将答案打到一个二维数组中,第一维是Cantor值,然后是一个字符串 int target[]={1,2,3,4,5,6,7,8,0}; // 目标状态 int tt[9]; struct Node{ // Node的信息代表 key是空白点在(x,y)的状态下的康托值,tol是拓展层数 int key,x,y,tol; Node(int _key,int _x,int _y,int _tol):key(_key),x(_x),y(_y),tol(_tol){} }; queue<Node> q; void bfs(){ // 初始化 memset(can,false,sizeof(can)); while(!q.empty()) q.pop(); int t_key=Cantor(target,9); // 找到目标状态康托值 can[t_key]=true; ans[t_key][0]='\0'; q.push(Node(t_key,2,2,0)); // 3x3 初始点x在(2,2) while(!q.empty()){ Node tmp=q.front(); q.pop(); unCantor(tmp.key+1,tt,9); // 将Cantor值对应的状态录入到数组tt中 int x=tmp.x, y=tmp.y; // 接下来4个if 代表上下左右走,因为是倒序BFS所以向上走时就是原来的向下走,其他相同 if(x>=1){ // 倒序向上走 swap(tt[x*3+y],tt[(x-1)*3+y]); // 交换两个格子 t_key=Cantor(tt,9); if(!can[t_key]){ q.push(Node(t_key,x-1,y,tmp.tol+1)); // 记录向上走后的状态,然后tol+1 can[t_key]=true; for(int i=0;i<tmp.tol;i++) ans[t_key][i]=ans[tmp.key][i]; // *继承父亲的路径 ans[t_key][tmp.tol]='d'; ans[t_key][tmp.tol+1]='\0'; } swap(tt[x*3+y],tt[(x-1)*3+y]); // 为什么每次都要交换过来,如果不能交换,当然得保持原样 } if(y>=1){ // 倒序向左走 swap(tt[x*3+y],tt[x*3+(y-1)]); t_key=Cantor(tt,9); if(!can[t_key]){ q.push(Node(t_key,x,y-1,tmp.tol+1)); can[t_key]=true; for(int i=0;i<tmp.tol;i++) ans[t_key][i]=ans[tmp.key][i]; ans[t_key][tmp.tol]='r'; ans[t_key][tmp.tol+1]='\0'; } swap(tt[x*3+y],tt[x*3+(y-1)]); } if(x<=1){ // 倒序向下走 swap(tt[x*3+y],tt[(x+1)*3+y]); t_key=Cantor(tt,9); if(!can[t_key]){ q.push(Node(t_key,x+1,y,tmp.tol+1)); can[t_key]=true; for(int i=0;i<tmp.tol;i++) ans[t_key][i]=ans[tmp.key][i]; ans[t_key][tmp.tol]='u'; ans[t_key][tmp.tol+1]='\0'; } swap(tt[x*3+y],tt[(x+1)*3+y]); } if(y<=1){ // 倒序向右走 swap(tt[x*3+y],tt[x*3+(y+1)]); t_key=Cantor(tt,9); if(!can[t_key]){ q.push(Node(t_key,x,y+1,tmp.tol+1)); can[t_key]=true; for(int i=0;i<tmp.tol;i++) ans[t_key][i]=ans[tmp.key][i]; ans[t_key][tmp.tol]='l'; ans[t_key][tmp.tol+1]='\0'; } swap(tt[x*3+y],tt[x*3+(y+1)]); } } } int d[9]; // 存放目标状态 void solve(){ int t_key=Cantor(d,9); if(!can[t_key]){ printf("unsolvable\n"); return; } int len=strlen(ans[t_key]); for(int i=len-1;i>=0;i--) printf("%c",ans[t_key][i]); printf("\n"); } int main(){ bfs(); // 反向BFS打表 #ifdef test freopen("Hdu 1043 Eight.txt","r",stdin); #endif string op; while(getline(cin,op)){ for(int i=0,j=0;i<op.size();i++){ if(op[i]>='1' && op[i]<='8') d[j++]=op[i]-'0'; if(op[i]=='x') d[j++]=0; } solve(); } return 0; }
相关文章推荐
- 关于Python的一些使用小技巧
- 状态管理---cookie、session
- 结构体
- 整数划分问题
- Oracle数据泵技术导入导出
- iPhone回美国是一条不归路?
- Histogram of Oriented Gridients(HOG) 方向梯度直方图
- 广工2016新生决赛 H《为什么会变成这样呢》 [位运算]【思维】【好题】
- java enum枚举
- MUI 页面传值 webview
- springmvc 集成apache cxf 开发webservice 示例
- ACM竞赛中用到的二进制处理方法(完善中)
- 在单片机上点亮LED
- 51nod 1627 瞬间移动
- 倒计时设置
- CCF 201312-5 I’m stuck!
- Atitit图像识别的常用特征大总结attilax大总结
- Java有没有goto关键字?
- Android/Java回调理解
- Atitit图像识别的常用特征大总结attilax大总结