bzoj1327: The Rotation Game
bz的这个题面啊。……是不是全世界只有没看原题面的我不知道要输出No moves needed……
题解
传说中名为IDA*的剪枝暴搜。
判断一下中间八个格子里最多数字的数量,如果8-这个数要大于深度限制,说明理想情况下这一次也不会出解,于是可以剪掉了。
代码
代码非常丑。
非常丑。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int now[24],loc,ed[]={6,7,8,11,12,15,16,17},tp[4],tot,sol[2017];
int mov[4][7]=
{0,2,6,11,15,20,22,
1,3,8,12,17,21,23,
10,9,8,7,6,5,4,
19,18,17,16,15,14,13},sad[]={0,0,0,0,1,0,3,2};
bool f;
void read(int &x)
{
char c=getchar();
while(c<'0'||c>'9')
c=getchar();
x=c-'0';
}
void dfs(int dep)
{
if(dep<0)return;
for(int i=1;i<4;i++)
tp[i]=0;
for(int i=0;i<8;i++)
tp[now[ed[i]]]++;
loc=1;
for(int i=2;i<4;i++)
if(tp[loc]<tp[i])
loc=i;
if(tp[loc]==8)
{
for(int i=0;i<tot;i++)
putchar(sol[i]+'A');
printf("\n%d\n",loc);
f=1;return;
}
if(8-tp[loc]>dep)return;
for(int i=0;i<8&&(!f);i++)
{
sol[tot++]=i;
if(i<4)
{
for(int j=6;j;j--)
swap(now[mov[i][0]],now[mov[i][j]]);
dfs(dep-1);
for(int j=0;j<6;j++)
swap(now[mov[i][6]],now[mov[i][j]]);
}
else
{
for(int j=0;j<6;j++)
swap(now[mov[sad[i]][6]],now[mov[sad[i]][j]]);
dfs(dep-1);
for(int j=6;j;j--)
swap(now[mov[sad[i]][0]],now[mov[sad[i]][j]]);
}
tot--;
}
}
int main()
{
read(now[0]);
while(now[0])
{
for(int i=1;i<24;i++)
read(now[i]);
tot=f=0;
for(int i=1;i<4;i++)
tp[i]=0;
for(int i=0;i<8;i++)
tp[now[ed[i]]]++;
loc=1;
for(int i=2;i<4;i++)
if(tp[loc]<tp[i])
loc=i;
if(tp[loc]==8)
{
printf("No moves needed\n%d\n",loc);
f=1;
}
for(int i=1;i<2017&&(!f);i++)
dfs(i);
read(now[0]);
}
}