Time Limit: 15000MS | Memory Limit: 150000K | |
Total Submissions: 6081 | Accepted: 2048 |
Description

Initially, the blocks are placed on the board randomly. Your task is to move the blocks so that the eight blocks placed in the center square have the same symbol marked. There is only one type of valid move, which is to rotate one of the four lines, each consisting of seven blocks. That is, six blocks in the line are moved towards the head by one block and the head block is moved to the end of the line. The eight possible moves are marked with capital letters A to H. Figure 1 illustrates two consecutive moves, move A and move C from some initial configuration.
Input
Output
Sample Input
1 1 1 1 3 2 3 2 3 1 3 2 2 3 1 2 2 2 3 1 2 1 3 3 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 0
Sample Output
AC 2 DDHH 2题意:一个“井”字形的玩具,上面有三种数字1、2、3,给出8种操作方式,A表示将第一个竖着的列循环上移一格,并且A和F是一个逆操作,B、C、D...的操作方式依此类推,初始状态给定,目标状态是中间8个数字相同。问最少的操作方式,并且要求给出操作的序列,步数一样的时候选择字典序最小的输出。图中的操作序列为AC。
思路:一开始的总体思路就是对的,不过有一个很难发现的坑坑了我一下午啊....
我们去枚举深度,在当前深度下进行DFS找有没有一种序列满足中间八个数字一样即可
注意有两个剪枝,第一个是这一次选择的字母不能和上一次对应,比如上一次选择了A,这次就不能选择F
第二个是因为每次移动在中间8个格子里最多多一个我们想要的数字,所以当前步数+尚未有我们想要的数字的格子数>深度的时候就return
这是个很高效的剪枝,15s的题可以再120ms过
另外,还有一个坑了我一下午的坑,我不知道其他人会不会跟我有一样的想法,这里姑且分享一下。
不能枚举数字,原因在于答案是要求字典序最小。而我们枚举数字找到一个合法的情况就break掉了,那么有可能出现就是你现在找到的合法情况中间数字是1,而有一种字典序更小的操作方式中间数字是2.如果你的思路和我一样,说到这里应该懂了吧。所以我们只要枚举深度就可以了,每次判断就判断三个数字即可。在当前深度下有一种能达到八个数字都相等就一定是字典序最小的了。如果你一定要枚举中间数字也不是不行,不过要把1~3三个数字都枚举完,有多个答案就取操作序列字典序小的。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int a[50],num[4];
char ans[1000],cnt;
int qian,hou;
void swap1(int &a1,int &a2,int &a3,int &a4,int &a5,int &a6,int &a7)
{
int temp=a1;
a1=a2,a2=a3,a3=a4,a4=a5,a5=a6,a6=a7,a7=temp;
}
int check(int *b)
{
int k=b[7];
if(k==b[8]&&k==b[9]&&k==b[12]&&k==b[13]&&k==b[16]&&k==b[17]&&k==b[18]) return 1;
return 0;
}
int solve(int *b)
{
int c[4];
c[1]=c[2]=c[3]=0;
c[b[7]]++,c[b[8]]++,c[b[9]]++;
c[b[12]]++,c[b[13]]++;
c[b[16]]++,c[b[17]]++,c[b[18]]++;
return max(c[1],max(c[2],c[3]));
}
int dfs(int dep,int now_dep,int last,int *b)
{
if(8-solve(b)+now_dep>dep||now_dep==dep) return 0;
if(last!=6)
{
swap1(b[1],b[3],b[7],b[12],b[16],b[21],b[23]);
if(check(b))
{
ans[++cnt]='A';
return 1;
}
if(dfs(dep,now_dep+1,1,b))
{
ans[++cnt]='A';
return 1;
}
swap1(b[23],b[21],b[16],b[12],b[7],b[3],b[1]);
}
if(last!=5)
{
swap1(b[2],b[4],b[9],b[13],b[18],b[22],b[24]);
if(check(b))
{
ans[++cnt]='B';
return 1;
}
if(dfs(dep,now_dep+1,2,b))
{
ans[++cnt]='B';
return 1;
}
swap1(b[24],b[22],b[18],b[13],b[9],b[4],b[2]);
}
if(last!=8)
{
swap1(b[11],b[10],b[9],b[8],b[7],b[6],b[5]);
if(check(b))
{
ans[++cnt]='C';
return 1;
}
if(dfs(dep,now_dep+1,3,b))
{
ans[++cnt]='C';
return 1;
}
swap1(b[5],b[6],b[7],b[8],b[9],b[10],b[11]);
}
if(last!=7)
{
swap1(b[20],b[19],b[18],b[17],b[16],b[15],b[14]);
if(check(b))
{
ans[++cnt]='D';
return 1;
}
if(dfs(dep,now_dep+1,4,b))
{
ans[++cnt]='D';
return 1;
}
swap1(b[14],b[15],b[16],b[17],b[18],b[19],b[20]);
}
if(last!=2)
{
swap1(b[24],b[22],b[18],b[13],b[9],b[4],b[2]);
if(check(b))
{
ans[++cnt]='E';
return 1;
}
if(dfs(dep,now_dep+1,5,b))
{
ans[++cnt]='E';
return 1;
}
swap1(b[2],b[4],b[9],b[13],b[18],b[22],b[24]);
}
if(last!=1)
{
swap1(b[23],b[21],b[16],b[12],b[7],b[3],b[1]);
if(check(b))
{
ans[++cnt]='F';
return 1;
}
if(dfs(dep,now_dep+1,6,b))
{
ans[++cnt]='F';
return 1;
}
swap1(b[1],b[3],b[7],b[12],b[16],b[21],b[23]);
}
if(last!=4)
{
swap1(b[14],b[15],b[16],b[17],b[18],b[19],b[20]);
if(check(b))
{
ans[++cnt]='G';
return 1;
}
if(dfs(dep,now_dep+1,7,b))
{
ans[++cnt]='G';
return 1;
}
swap1(b[20],b[19],b[18],b[17],b[16],b[15],b[14]);
}
if(last!=3)
{
swap1(b[5],b[6],b[7],b[8],b[9],b[10],b[11]);
if(check(b))
{
ans[++cnt]='H';
return 1;
}
if(dfs(dep,now_dep+1,8,b))
{
ans[++cnt]='H';
return 1;
}
swap1(b[11],b[10],b[9],b[8],b[7],b[6],b[5]);
}
return 0;
}
int main()
{
int b[50];
while(~scanf("%d",&a[1])&&a[1])
{
for(int i=2; i<=24; i++)
scanf("%d",&a[i]);
int flag=0;
memset(num,0,sizeof(num));
num[a[7]]++,num[a[8]]++,num[a[9]]++;
num[a[12]]++,num[a[13]]++;
num[a[16]]++,num[a[17]]++,num[a[18]]++;
if(num[1]==8||num[2]==8||num[3]==8)
{
printf("No moves needed\n%d\n",a[7]);
continue;
}
for(int dep=1; !flag; dep++)
{
cnt=0;
memcpy(b,a,sizeof(b));
if(dfs(dep,0,0,b))
{
flag=1;
for(int j=cnt; j>0; j--)
printf("%c",ans[j]);
printf("\n%d\n",b[7]);
break;
}
}
}
return 0;
}