无题
题目链接: 无题I
题意
在一个4*4的矩阵中分别有4个1,4个2,4个3和4个4分别表示4种不同的东西,每一步小A可以把同一行的4个数往左移或者往右移一步或者把同一列的4个数字往上移或者往下移一步(1,2,3,4往左移后是2,3,4,1),小A现在想知道进过最少的几步移动可以将矩阵的每行上的4个数字都一样或者每列上的4个数字都一样。
思路
直接暴力DFS即可。但是适当的剪枝可以大大优化算法的复杂性,可以说是运用了简单的A*技巧吧。
就单单加了一个get_h函数后,就可以剪掉大部分无用的搜索了
代码
#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
typedef double db;
typedef long long ll;
const int MAXN = (int)1e6+7;
const int INF = (int)0x3f3f3f3f;
int pic[6][6];
int res;
bool check() {
int flag = 0;
rep(i,1,4) {
if (pic[i][1] == pic[i][2] && pic[i][1] == pic[i][3] && pic[i][1] == pic[i][4]) flag ++;
}
if (flag == 4) return true;
flag = 0;
rep(i,1,4) {
if (pic[1][i] == pic[2][i] && pic[1][i] == pic[3][i] && pic[1][i] == pic[4][i]) flag ++;
}
return flag == 4;
}
void rotx(int ip,int x) {
if (x == 0) {pic[ip][5] = pic[ip][1]; rep(i,1,4) pic[ip][i] = pic[ip][i+1]; }
else {pic[ip][0] = pic[ip][4]; per(i,4,1) pic[ip][i] = pic[ip][i-1]; }
}
void roty(int jp,int x) {
if (x == 0) {pic[5][jp] = pic[1][jp]; rep(i,1,4) pic[i][jp] = pic[i+1][jp]; }
else {pic[0][jp] = pic[4][jp]; per(i,4,1) pic[i][jp] = pic[i-1][jp]; }
}
void show() {
rep(i,1,4) {
rep(j,1,4) cout << pic[i][j] << ' ';
cout << endl;
}cout << "====================================" << endl;
}
int flag;
int get_h() {
int r[5][5],c[5][5];
mmm(r,0);mmm(c,0);
rep(i,1,4) {
rep(j,1,4) {
r[i][pic[i][j]] ++;
c[j][pic[i][j]] ++;
}
}
int sumc = 0,sumr = 0;
rep(i,1,4) {
int mr = 0,mc = 0;
rep(j,1,4) {
mr = max(mr,r[i][j]);
mc = max(mc,c[i][j]);
}
sumc += mc;
sumr += mr;
}
return 4*4-max(sumc,sumr);
}
void dfs(int sum) {
int h = get_h(); //剪枝的核心
if (sum == 0){
if (h == 0) flag = 1;
return ;
}
if (h > sum*4) return ; //神奇
rep(i,1,4) {
rep(k,0,1) {
rotx(i,k); dfs(sum-1); if (flag) return ; rotx(i,k^1);
roty(i,k); dfs(sum-1); if (flag) return ; roty(i,k^1);
}
}
return ;
}
int main()
{
int T;
scanf("%d",&T);
while (T --) {
rep(i,1,4) {
rep(j,1,4) {
scanf("%d",&pic[i][j]);
}
}
flag = 0;
int res = 0;
rep(i,1,5) {
dfs(i);
if (flag) {
res = i;
break;
}
}
if (res) printf("%d\n",res);
else printf("-1\n");
}
}
/*
1 1 2 2
2 2 3 3
3 3 4 4
4 4 1 1
*/