对应POJ题目:点击打开链接
题目意思
给出24个数字(其中1,2,3各有8个) 例如下图
每一次操作 例如 A 操作把 A 旁边的数字放到 A 所在的那一行数字的另一端的末尾 然后其他数字往 A 的方向移一格
即 1 1 3 2 2 2 3 变成 1 3 2 2 2 3 1
如果执行 C 操作的话 3 2 2 2 3 1 3 就变成 3 3 2 2 2 3 1
现在问最少要多少次操作才能使中间那8个数字变成一样的数字 输出最少的操作数和中间8个数字变得一样的时候是哪一个数字
思路:迭代加深,逐层搜索,具体看代码;
#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std;
const int INF=1<<30;
const int MAXN=7500+10;
int maxh,c;
int num[30];
int res[10];
int A[8][7]={ 1,3,7,12,16,21,23,//井字的每一笔
2,4,9,13,18,22,24,
11,10,9,8,7,6,5,
20,19,18,17,16,15,14,
24,22,18,13,9,4,2,
23,21,16,12,7,3,1,
14,15,16,17,18,19,20,
5,6,7,8,9,10,11};
bool judge(int *a)//判断中间8格是否全部相同
{
int t=a[7];
if(a[8]!=t || a[9]!=t || a[12]!=t
|| a[13]!=t || a[16]!=t || a[17]!=t || a[18]!=t)
return 0;
return 1;
}
int cal(int *a)//返回中间8格中最少的不同数字的数量
{
int b[5]={0};
b[a[7]]++;b[a[8]]++;b[a[9]]++;b[a[12]]++;
b[a[13]]++;b[a[16]]++;b[a[17]]++;b[a[18]]++;
b[0]=b[1]>b[2]?b[1]:b[2];
b[0]=b[0]>b[3]?b[0]:b[3];
return 8-b[0];
}
bool dfs(int deep)//逐层搜索
{
int n=cal(num);
if(n==0) return true;//中间8格全部相同
if(n>maxh-deep) return false;//中间8格中最少的不同数字的数量大于还可以搜索的层数,不可能有解
for(int i=0; i<8; i++){
res[c++]=i;
int tmp=num[A[i][0]];
for(int j=1; j<7; j++){
num[A[i][j-1]]=num[A[i][j]];
}
num[A[i][6]]=tmp;
if(dfs(deep+1)) return true;
c--;
tmp=num[A[i][6]];
for(int j=6; j>0; j--){
num[A[i][j]]=num[A[i][j-1]];
}
num[A[i][0]]=tmp;
}
return false;
}
int main()
{
//freopen("in.txt","r",stdin);
int x;
while(scanf("%d", &x), x)
{
num[1]=x;
int i;
for(i=2; i<=24; i++){
scanf("%d", &x);
num[i]=x;
}
if(judge(num)){
printf("No moves needed\n");
printf("%d\n", num[7]);
continue;
}
maxh=1;
c=0;
while(!dfs(0))
{
maxh++;
}
for(i=0; i<c; i++){
printf("%c",res[i]+'A');
}
printf("\n%d\n", num[7]);
}
return 0;
}