The Rotation Game[POJ2286]

版权声明:作为一个蒟蒻,转载时请通知我这个蒟蒻 https://blog.csdn.net/zyszlb2003/article/details/89444755

欢迎大家访问我的老师的OJ———caioj.cn

题面描述

见原题

思路

首先给出如何读入数据

while(scanf("%d",&a[1][3])&&a[1][3])solve();
scanf("%d%d%d",&a[1][5],&a[2][3],&a[2][5]);
for(int i=1;i<=7;i++)scanf("%d",&a[3][i]);
scanf("%d%d",&a[4][3],&a[4][5]);
for(int i=1;i<=7;i++)scanf("%d",&a[5][i]);
scanf("%d%d%d%d",&a[6][3],&a[6][5],&a[7][3],&a[7][5]);

如何改变状态

void work(int k)
{
	if(k==1)
	{
		for(int i=1;i<8;i++)a[i-1][3]=a[i][3];
		a[7][3]=a[0][3];
	}
	else if(k==2)
	{
		for(int i=1;i<8;i++)a[i-1][5]=a[i][5];
		a[7][5]=a[0][5];
	}
	else if(k==3)
	{
		for(int i=7;i;i--)a[3][i+1]=a[3][i];
		a[3][1]=a[3][8];
	}
	else if(k==4)
	{
		for(int i=7;i;i--)a[5][i+1]=a[5][i];
		a[5][1]=a[5][8];
	}
	else if(k==5)
	{
		for(int i=7;i;i--)a[i+1][5]=a[i][5];
		a[1][5]=a[8][5];
	}
	else if(k==6)
	{
		for(int i=7;i;i--)a[i+1][3]=a[i][3];
		a[1][3]=a[8][3];
	}
	else if(k==7)
	{
		for(int i=1;i<8;i++)a[5][i-1]=a[5][i];
		a[5][7]=a[5][0];
	}
	else
	{
		for(int i=1;i<8;i++)a[3][i-1]=a[3][i];
		a[3][7]=a[3][0];
	}
}

这道题的输入是真的鬼畜啊
直接爆搜肯定不行。
所以我们用 IDA* \operatorname{IDA*} 来爆搜
首先限制深度,
8个数中最多出现次数的数字 k k ,设与 k k 不同的个数 m m
通过观察可以发现,我们取m为估价函数。因为我们至少要使这 m m 个数变为 k k 才能满足条件.
总而言之,当"当前操作次数+估价> dep \large\operatorname{dep} "时,就回溯。
另外,有一个重要剪枝,不要执行上一次执行的操作的逆操作,因为这样等价于无效

int c=ans[len]-'A'+1;
if(c==1&&i==6)continue;
else if(c==2&&i==5)continue;
else if(c==3&&i==8)continue;
else if(c==4&&i==7)continue;
else if(c==5&&i==2)continue;
else if(c==6&&i==1)continue;
else if(c==7&&i==4)continue;
else if(c==8&&i==3)continue;

完整代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
using namespace std;
const char A[9]={'0','A','B','C','D','E','F','G','H'};
int a[11][11],dep;
char ans[121];
void work(int k)
{
	if(k==1)
	{
		for(int i=1;i<8;i++)a[i-1][3]=a[i][3];
		a[7][3]=a[0][3];
	}
	else if(k==2)
	{
		for(int i=1;i<8;i++)a[i-1][5]=a[i][5];
		a[7][5]=a[0][5];
	}
	else if(k==3)
	{
		for(int i=7;i;i--)a[3][i+1]=a[3][i];
		a[3][1]=a[3][8];
	}
	else if(k==4)
	{
		for(int i=7;i;i--)a[5][i+1]=a[5][i];
		a[5][1]=a[5][8];
	}
	else if(k==5)
	{
		for(int i=7;i;i--)a[i+1][5]=a[i][5];
		a[1][5]=a[8][5];
	}
	else if(k==6)
	{
		for(int i=7;i;i--)a[i+1][3]=a[i][3];
		a[1][3]=a[8][3];
	}
	else if(k==7)
	{
		for(int i=1;i<8;i++)a[5][i-1]=a[5][i];
		a[5][7]=a[5][0];
	}
	else
	{
		for(int i=1;i<8;i++)a[3][i-1]=a[3][i];
		a[3][7]=a[3][0];
	}
}
int gj()
{
	int num[4];num[1]=num[2]=num[3]=0;
	for(int i=3;i<=5;i++)
		for(int j=3;j<=5;j++)
		if(!(i==4&&j==4))
		{
			++num[a[i][j]];
		}
	return 8-max(num[1],max(num[2],num[3]));
}
int len;
bool dfs(int now)
{
	int cnt=gj();
	if(!cnt)return 1;
	if(now+cnt>dep)return 0;
	int b[11][11];
	memcpy(b,a,sizeof(a));
	for(int i=1;i<9;i++)
	{
		if(len!=0)
		{
			int c=ans[len]-'A'+1;
			if(c==1&&i==6)continue;
			else if(c==2&&i==5)continue;
			else if(c==3&&i==8)continue;
			else if(c==4&&i==7)continue;
			else if(c==5&&i==2)continue;
			else if(c==6&&i==1)continue;
			else if(c==7&&i==4)continue;
			else if(c==8&&i==3)continue;
		}
		ans[++len]=A[i];work(i);
		if(dfs(now+1))return 1;
		--len;
		memcpy(a,b,sizeof(b));
	}
	return 0;
}
void solve()
{
	scanf("%d%d%d",&a[1][5],&a[2][3],&a[2][5]);
	for(int i=1;i<=7;i++)scanf("%d",&a[3][i]);
	scanf("%d%d",&a[4][3],&a[4][5]);
	for(int i=1;i<=7;i++)scanf("%d",&a[5][i]);
	scanf("%d%d%d%d",&a[6][3],&a[6][5],&a[7][3],&a[7][5]);
	dep=0;len=0;
	while(!dfs(0))++dep;
	if(!dep)puts("No moves needed");
	else 
	{
		for(int i=1;i<=len;i++)putchar(ans[i]);
		puts("");
	}
	printf("%d\n",a[3][3]);
}
int main()
{
	while(scanf("%d",&a[1][3])&&a[1][3])solve();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zyszlb2003/article/details/89444755