hdu 2234(IDA*)

题目链接: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 }
View Code

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值