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\n", '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\n", 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\n", 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('\n');
printf("%d\n", c);
break;
}
}
}
return 0;
}