版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Ronaldo7_ZYB/article/details/89020138
题目描述
一个井字形棋盘,上面有24个格子(如下图)。
这些格子上面有1,2,3三种数字, 且每种数字有 8 格。一开始,这些格子上的数字是随机分布的。
你的任务是移动这些格 子使得中间 8 个格子的数字相同。有 8 种移动方式,分别标记为 A 到 H,可以理解为 拉动 4 条链,如图的变换为“AC”。
问至少需要多少次拉动,才能从初始状态到达目标 状态?(保证数据有解)
题解
算法是 ,因为在数据范围中保证了步数一定小于 因此可以想到迭代加深算法。
每一次移动中我们可以知道对于中间的八个格子,走了一个,进来了一个;因此比表理想的情况就是走的是和其他格子不同的,进来的是相同的。因此我们可以统计格子内数字重复最多的那个数,并记那个数 ,则 。
然后状态暴力标记改变即可。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int MAX;
struct node
{
char s[25];
node change1(void)
{
node temp;
for (int i=1;i<=24;++i) temp.s[i]=s[i];
temp.s[5]=s[11];
temp.s[6]=s[5];
temp.s[7]=s[6];
temp.s[8]=s[7];
temp.s[9]=s[8];
temp.s[10]=s[9];
temp.s[11]=s[10];
return temp;
}
//H
node change2(void)
{
node temp;
for (int i=1;i<=24;++i) temp.s[i]=s[i];
temp.s[5]=s[6];
temp.s[6]=s[7];
temp.s[7]=s[8];
temp.s[8]=s[9];
temp.s[9]=s[10];
temp.s[10]=s[11];
temp.s[11]=s[5];
return temp;
}
//C
node change3(void)
{
node temp;
for (int i=1;i<=24;++i) temp.s[i]=s[i];
temp.s[1]=s[3];
temp.s[3]=s[7];
temp.s[7]=s[12];
temp.s[12]=s[16];
temp.s[16]=s[21];
temp.s[21]=s[23];
temp.s[23]=s[1];
return temp;
}
//A
node change4(void)
{
node temp;
for (int i=1;i<=24;++i) temp.s[i]=s[i];
temp.s[1]=s[23];
temp.s[3]=s[1];
temp.s[7]=s[3];
temp.s[12]=s[7];
temp.s[16]=s[12];
temp.s[21]=s[16];
temp.s[23]=s[21];
return temp;
}
//F
node change5(void)
{
node temp;
for (int i=1;i<=24;++i) temp.s[i]=s[i];
temp.s[2]=s[4];
temp.s[4]=s[9];
temp.s[9]=s[13];
temp.s[13]=s[18];
temp.s[18]=s[22];
temp.s[22]=s[24];
temp.s[24]=s[2];
return temp;
}
//B
node change6(void)
{
node temp;
for (int i=1;i<=24;++i) temp.s[i]=s[i];
temp.s[2]=s[24];
temp.s[4]=s[2];
temp.s[9]=s[4];
temp.s[13]=s[9];
temp.s[18]=s[13];
temp.s[22]=s[18];
temp.s[24]=s[22];
return temp;
}
//E
node change7(void)
{
node temp;
for (int i=1;i<=24;++i) temp.s[i]=s[i];
temp.s[14]=s[15];
temp.s[15]=s[16];
temp.s[16]=s[17];
temp.s[17]=s[18];
temp.s[18]=s[19];
temp.s[19]=s[20];
temp.s[20]=s[14];
return temp;
}
//G
node change8(void)
{
node temp;
for (int i=1;i<=24;++i) temp.s[i]=s[i];
temp.s[14]=s[20];
temp.s[15]=s[14];
temp.s[16]=s[15];
temp.s[17]=s[16];
temp.s[18]=s[17];
temp.s[19]=s[18];
temp.s[20]=s[19];
return temp;
}
//D
int func(void)
{
int cnt[3];
cnt[0]=cnt[1]=cnt[2]=0;
cnt[s[7]-'1'] ++;
cnt[s[8]-'1'] ++;
cnt[s[9]-'1'] ++;
cnt[s[12]-'1'] ++;
cnt[s[16]-'1'] ++;
cnt[s[13]-'1'] ++;
cnt[s[18]-'1'] ++;
cnt[s[17]-'1'] ++;
if (cnt[0]>=cnt[1] && cnt[0]>=cnt[2]) return cnt[1]+cnt[2];
if (cnt[1]>=cnt[0] && cnt[1]>=cnt[2]) return cnt[0]+cnt[2];
if (cnt[2]>=cnt[0] && cnt[2]>=cnt[1]) return cnt[0]+cnt[1];
}
//估价函数
};
bool dfs(node now,int x)
{
if (x==MAX)
{
if (now.func()==0)
{
printf("%d\n",MAX);
return 1;
}
return 0;
}
if (x+now.func()>MAX) return 0;
if (dfs(now.change1(),x+1)) return 1;
if (dfs(now.change2(),x+1)) return 1;
if (dfs(now.change3(),x+1)) return 1;
if (dfs(now.change4(),x+1)) return 1;
if (dfs(now.change5(),x+1)) return 1;
if (dfs(now.change6(),x+1)) return 1;
if (dfs(now.change7(),x+1)) return 1;
if (dfs(now.change8(),x+1)) return 1;
return 0;
}
void work(void)
{
node ST;
cin>>ST.s[1];
if (ST.s[1]=='0') exit(0);
for (int i=2;i<=24;++i) cin>>ST.s[i];
for (MAX=0;MAX<=12;++MAX)
if (dfs(ST,0)) return;
return;
}
int main(void)
{
freopen("jing.in","r",stdin);
freopen("jing.out","w",stdout);
while (1) work();
return 0;
}