https://vjudge.net/problem/UVA-1343
题目
给出一种井字棋盘,只含数字1、2、3,只允许六种移动,问如何移动才能使棋盘中间八格数字相等,输出步数最少的操作,如果有多个步数相同的操作,输出字典序最小的操作
题解
每一步操作都有点麻烦,先写个工具模拟所有操作
先编号,方便输入和操作
只看A操作
操作后下面的数占据了上面的位置,然后就可以写程序得到每个数的新位置
工具代码
#include<bits/stdc++.h> using namespace std; #define REP(i,x,y) for(register int i=(x); i<(y); i++) int arr[7][7] = { {0,0,1,0,2,0,0}, {0,0,3,0,4,0,0}, {5,6,7,8,9,10,11}, {0,0,12,0,13,0,0}, {14,15,16,17,18,19,20}, {0,0,21,0,22,0,0}, {0,0,23,0,24,0,0} }; int arr2[7][7]; inline void op(int fx, int fy, int dx, int dy) { int ix=fx+dx,iy=fy+dy; while(0<=ix && ix<7 && 0<=iy && iy<7) { arr2[ix][iy]=arr[ix-dx][iy-dy]; ix+=dx, iy+=dy; } arr2[fx][fy]=arr[ix-dx][iy-dy]; } int main() { const int fx[] = {0,0,2,4,6,6,4,2}; const int fy[] = {2,4,6,6,4,2,0,0}; const int dx[] = {1,1,0,0,-1,-1,0,0}; const int dy[] = {0,0,-1,-1,0,0,1,1}; REP(i,0,8) { printf("{"); memcpy(arr2,arr,sizeof arr); op(fx[i],fy[i],dx[i],dy[i]); REP(i,0,7) { REP(j,0,7) { if(arr2[i][j]) printf("%d,", arr2[i][j]-1); } } printf("}, // %c ", 'A'+i); } return 0; }
然后就可以用IDA*写程序代码了……(因为不想写hash= =)
AC代码
#include<bits/stdc++.h> using namespace std; #define REP(i,x,y) for(register int i=(x); i<(y); i++) #define _REP(i,x,y) for(i=(x); i<(y); i++) #define REPE(i,x,y) for(register int i=(x); i<=(y); i++) #define _REPE(i,x,y) for(i=(x); i<=(y); i++) #ifdef sahdsg #define DBG(a,...) printf(a, ##__VA_ARGS__) #else #define DBG(a,...) (void)0 #endif const int mv[8][24] = { {22,1,0,3,4,5,2,7,8,9,10,6,12,13,14,11,16,17,18,19,15,21,20,23}, // A {0,23,2,1,4,5,6,7,3,9,10,11,8,13,14,15,16,12,18,19,20,17,22,21}, // B {0,1,2,3,5,6,7,8,9,10,4,11,12,13,14,15,16,17,18,19,20,21,22,23}, // C {0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18,19,13,20,21,22,23}, // D {0,3,2,8,4,5,6,7,12,9,10,11,17,13,14,15,16,21,18,19,20,23,22,1}, // E {2,1,6,3,4,5,11,7,8,9,10,15,12,13,14,20,16,17,18,19,22,21,0,23}, // F {0,1,2,3,4,5,6,7,8,9,10,11,12,19,13,14,15,16,17,18,20,21,22,23}, // G {0,1,2,3,10,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23} // H }; int arr[24]; int target; const int vi[]={6,7,8,11,12,15,16,17}; int md; char ans[4][450]; bool dfs(int *oarr, int d) { int e=0; REP(i,0,8) { if(oarr[vi[i]]!=target) e++; } // DBG("#%d %d ", d,e); if(e+d>md) return false; if(e==0) return true; int narr[24]; REP(i,0,8) { REP(j,0,24) { narr[mv[i][j]]=oarr[j]; } ans[target][d]='A'+i; // putchar(ans[d]); if(dfs(narr, d+1)) return true; } return false; } int main() { #ifdef sahdsg freopen("in.txt", "r", stdin); #endif while(~scanf("%d", arr) && arr[0]) { REP(i,1,24) { scanf("%d", &arr[i]); } for(md=0;;md++) { bool f = false; for(target=1;target<=3;target++) { ans[target][0]=0; if(dfs(arr,0)) { if(md==0) { puts("No moves needed"); printf("%d ", target); break; } f=true; } } if(f) { int c=-1; REPE(i,1,3) { if(ans[i][0]!=0 && ((c==-1) || (strcmp(ans[i],ans[c])<0))) { c=i; } } if(c==-1) break; REP(i,0,md) { putchar(ans[c][i]); } putchar(' '); printf("%d ", c); break; } } } return 0; }