题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2234
思路:IDA*可以搞,借鉴的是大牛的启发式函数h(): 可以考虑把每一行上的数转化成相同的,或者把每一列上的数字转化成相同的,二者取最小值。
1 1 3 2
2 4 4 2
3 3 1 4
1 2 3 4
如果把这个矩阵转化成行相同的话需要的操作:第一行 至少要2次,第二行也是2次, 第三行是2次,第四行是3次, 所以把矩阵转化成行相同至少要3次。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 int map[5][5]; 8 int maxdeep; 9 10 bool Judge() 11 { 12 if(map[1][1]!=map[1][2]){ 13 for(int i=1;i<=4;i++) 14 for(int j=1;j<=4;j++) 15 if(map[j][i]!=map[i][i])return false; 16 return true; 17 }else { 18 for(int i=1;i<=4;i++) 19 for(int j=1;j<=4;j++) 20 if(map[i][j]!=map[i][1])return false; 21 return true; 22 } 23 } 24 25 int Get_H() 26 { 27 int step1=0,step2=0; 28 for(int i=1;i<=4;i++){ 29 int num[5]={0},ans=0; 30 for(int j=1;j<=4;j++)num[map[i][j]]++; 31 for(int j=1;j<=4;j++)ans=max(ans,num[j]); 32 step1=max(step1,4-ans); 33 } 34 for(int j=1;j<=4;j++){ 35 int num[5]={0},ans=0; 36 for(int i=1;i<=4;i++)num[map[i][j]]++; 37 for(int i=1;i<=4;i++)ans=max(ans,num[i]); 38 step2=max(step2,4-ans); 39 } 40 return min(step1,step2); 41 } 42 43 void Move_L(int i) 44 { 45 int tmp=map[i][1]; 46 for(int j=2;j<=4;j++)map[i][j-1]=map[i][j]; 47 map[i][4]=tmp; 48 } 49 50 void Move_R(int i) 51 { 52 int tmp=map[i][4]; 53 for(int j=4;j>=2;j--)map[i][j]=map[i][j-1]; 54 map[i][1]=tmp; 55 } 56 57 void Move_U(int j) 58 { 59 int tmp=map[1][j]; 60 for(int i=2;i<=4;i++)map[i-1][j]=map[i][j]; 61 map[4][j]=tmp; 62 } 63 64 void Move_D(int j) 65 { 66 int tmp=map[4][j]; 67 for(int i=4;i>=2;i--)map[i][j]=map[i-1][j]; 68 map[1][j]=tmp; 69 } 70 71 72 bool IDA_star(int deep) 73 { 74 if(deep==maxdeep)return Judge(); 75 if(Get_H()+deep>maxdeep)return false; 76 77 for(int i=1;i<=4;i++){ 78 Move_L(i); 79 if(IDA_star(deep+1))return true; 80 Move_R(i); 81 82 Move_R(i); 83 if(IDA_star(deep+1))return true; 84 Move_L(i); 85 } 86 for(int j=1;j<=4;j++){ 87 Move_U(j); 88 if(IDA_star(deep+1))return true; 89 Move_D(j); 90 91 Move_D(j); 92 if(IDA_star(deep+1))return true; 93 Move_U(j); 94 } 95 return false; 96 } 97 98 int main() 99 { 100 int _case; 101 scanf("%d",&_case); 102 while(_case--){ 103 for(int i=1;i<=4;i++) 104 for(int j=1;j<=4;j++)scanf("%d",&map[i][j]); 105 if(Judge()){ 106 puts("0"); 107 continue; 108 } 109 maxdeep=1; 110 while(maxdeep<=5){ 111 if(IDA_star(0))break; 112 maxdeep++; 113 } 114 if(maxdeep<=5){ 115 printf("%d\n",maxdeep); 116 }else 117 puts("-1"); 118 } 119 return 0; 120 }