题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2234
题目意思是一个4*4矩阵里面有4个1,4个2,4个3,4个4,每一步可以将矩阵的某一行向左移一步或向右移一步,或者将矩阵的某一列向上或向下移一步,问能是否在5步内使矩阵的每一行或者每一列都一样,如果在5步内的话,输出确定的最小步数,大于5步输出-1。
依然是迭代深搜,同时A*剪枝,考虑移动一行做多只能使列上相同数字+1,移动一列也只能使行上相同数字+1,那么估值函数可以记为使每行相同所需要的步数以及使每列相同所需要的步数的最小值。
代码:
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<cmath>
#include<vector>
#include<map>
#include<stack>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define scanfprint() freopen("input.txt","r",stdin)
#define printfprint() freopen("output.txt","w",stdout)
#define mem(a,b) memset(a,b,sizeof(a))
const int spot=1000+10;
const int edge=100000+10;
const int maxn=10;
const double pi=acos(-1.0);
const int mod=1e9+7;
const double ips=0.000001;
int n,m,a[maxn][maxn],ans,num[6];
bool flag[maxn];
bool check_row() //检查行
{
int i;
for(i=1; i<=4; i++)
if(!(a[i][1]==a[i][2]&&a[i][1]==a[i][3]&&a[i][1]==a[i][4]))
return 0;
return 1;
}
bool check_col() //检查列
{
int i;
for(i=1; i<=4; i++)
if(!(a[1][i]==a[2][i]&&a[1][i]==a[3][i]&&a[1][i]==a[4][i]))
return 0;
return 1;
}
int judge_row(int row) //判断此行存在最多的数字的数量
{
mem(num,0);
int i;
for(i=1; i<=4; i++)
num[a[row][i]]++;
return max(max(num[1],num[2]),max(num[3],num[4]));
}
int judge_col(int col) //判断此列存在最多的数字的数量
{
mem(num,0);
int i;
for(i=1; i<=4; i++)
num[a[i][col]]++;
return max(max(num[1],num[2]),max(num[3],num[4]));
}
int h() //估值函数
{
int i,row=0,col=0;
for(i=1; i<=4; i++)
row+=4-judge_row(i);
for(i=1; i<=4; i++)
col+=4-judge_col(i);
return (min(row,col)+3)/4;//移动一次可以交换4个位置,最少所需要的步数
}
bool dfs(int dep,int last)
{
// printf("dep=%d,last=%d\n",dep,last);
int i,j,temp;
if(h()+dep>ans)
return 0;
if(check_col()||check_row())
return 1;
int tmp[maxn][maxn];
memcpy(tmp,a,sizeof(tmp));
for(i=1; i<=16; i++)
{
if(last+i!=17)
{
if(i<=4)
{
temp=a[1][i];
for(j=1; j<=3; j++)
a[j][i]=a[j+1][i];
a[j][i]=temp;
}
else if(i<=8)
{
temp=a[i-4][1];
for(j=1; j<=3; j++)
a[i-4][j]=a[i-4][j+1];
a[i-4][j]=temp;
}
else if(i<=12)
{
temp=a[13-i][4];
for(j=4; j>=2; j--)
a[13-i][j]=a[13-i][j-1];
a[13-i][j]=temp;
}
else
{
temp=a[4][17-i];
for(j=4; j>=2; j--)
a[j][17-i]=a[j-1][17-i];
a[j][17-i]=temp;
}
if(dfs(dep+1,i))
return 1;
else
memcpy(a,tmp,sizeof(a));
}
}
return 0;
}
int main()
{
int nn,i,j;
scanf("%d",&nn);
while(nn--)
{
for(i=1; i<=4; i++)
for(j=1; j<=4; j++)
scanf("%d",&a[i][j]);
ans=1;
for(;;)
{
if(dfs(0,-1))
{
printf("%d\n",ans);
break;
}
ans++;
if(ans>5)
{
printf("-1\n");
break;
}
}
}
return 0;
}