hdu 1667(IDA*)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1667

思路:大牛说是IDA*的入门题=.=构造h()=8-max(1,2,3);  max(1,2,3)表示中间的八个位置中出现最多的数的个数。 因为每次操作只能改变中间8个中的一个,所以可以这样构造启发式函数。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<string>
  6 using namespace std;
  7 int map[10][10];
  8 int maxdeep;
  9 char ans[111];
 10 
 11 bool Judge()
 12 {
 13     if(map[3][3]!=map[3][4])return false;
 14     if(map[3][3]!=map[3][5])return false;
 15     if(map[3][3]!=map[4][3])return false;
 16     if(map[3][3]!=map[4][5])return false;
 17     if(map[3][3]!=map[5][3])return false;
 18     if(map[3][3]!=map[5][4])return false;
 19     if(map[3][3]!=map[5][5])return false;
 20     return true;
 21 }
 22 
 23 int Get_H()
 24 {
 25     int MAX=0,pos[4]={0};
 26     for(int i=3;i<=5;i++){
 27         pos[map[i][3]]++;
 28         pos[map[i][5]]++;
 29     }
 30     pos[map[3][4]]++;
 31     pos[map[5][4]]++;
 32     for(int i=1;i<=3;i++)MAX=max(MAX,pos[i]);
 33     return 8-MAX;
 34 }
 35 
 36 void Move_A()
 37 {
 38     int tmp=map[1][3];
 39     for(int i=2;i<=7;i++)map[i-1][3]=map[i][3];
 40     map[7][3]=tmp;
 41 }
 42 
 43 void Move_B()
 44 {
 45     int tmp=map[1][5];
 46     for(int i=2;i<=7;i++)map[i-1][5]=map[i][5];
 47     map[7][5]=tmp;
 48 }
 49 
 50 void Move_C()
 51 {
 52     int tmp=map[3][7];
 53     for(int i=7;i>=2;i--)map[3][i]=map[3][i-1];
 54     map[3][1]=tmp;
 55 }
 56 
 57 void Move_D()
 58 {
 59     int tmp=map[5][7];
 60     for(int i=7;i>=2;i--)map[5][i]=map[5][i-1];
 61     map[5][1]=tmp;
 62 }
 63 
 64 void Move_E()
 65 {
 66     int tmp=map[7][5];
 67     for(int i=7;i>=2;i--)map[i][5]=map[i-1][5];
 68     map[1][5]=tmp;
 69 }
 70 
 71 void Move_F()
 72 {
 73     int tmp=map[7][3];
 74     for(int i=7;i>=2;i--)map[i][3]=map[i-1][3];
 75     map[1][3]=tmp;
 76 }
 77 
 78 void Move_G()
 79 {
 80     int tmp=map[5][1];
 81     for(int i=2;i<=7;i++)map[5][i-1]=map[5][i];
 82     map[5][7]=tmp;
 83 }
 84 
 85 void Move_H()
 86 {
 87     int tmp=map[3][1];
 88     for(int i=2;i<=7;i++)map[3][i-1]=map[3][i];
 89     map[3][7]=tmp;
 90 }
 91         
 92 bool IDA_star(int deep)
 93 {
 94     if(deep==maxdeep)return Judge();
 95     if(Get_H()+deep>maxdeep)return false;
 96 
 97     ans[deep]='A';
 98     Move_A();
 99     if(IDA_star(deep+1))return true;
100     Move_F();
101     
102     ans[deep]='B';
103     Move_B();
104     if(IDA_star(deep+1))return true;
105     Move_E();
106 
107     ans[deep]='C';
108     Move_C();
109     if(IDA_star(deep+1))return true;
110     Move_H();
111 
112     ans[deep]='D';
113     Move_D();
114     if(IDA_star(deep+1))return true;
115     Move_G();
116 
117     ans[deep]='E';
118     Move_E();
119     if(IDA_star(deep+1))return true;
120     Move_B();
121 
122     ans[deep]='F';
123     Move_F();
124     if(IDA_star(deep+1))return true;
125     Move_A();
126 
127     ans[deep]='G';
128     Move_G();
129     if(IDA_star(deep+1))return true;
130     Move_D();
131 
132     ans[deep]='H';
133     Move_H();
134     if(IDA_star(deep+1))return true;
135     Move_C();
136     return false;
137 }
138 
139 
140 int main()
141 {
142     memset(map,0,sizeof(map));
143     for(int i=1;i<=7;i++)map[i][3]=map[i][5]=1;
144     for(int i=1;i<=7;i++)map[3][i]=map[5][i]=1;
145     while(true){
146         for(int i=1;i<=7;i++){
147             for(int j=1;j<=7;j++){
148                 if(map[i][j]==0)continue;
149                 scanf("%d",&map[i][j]);
150                 if(map[i][j]==0)return 0;
151             }
152         }
153         if(Judge()){
154             puts("No moves needed");
155             printf("%d\n",map[3][3]);
156             continue;
157         }
158         for(maxdeep=1; ;maxdeep++){
159             if(IDA_star(0))break;
160         }
161         ans[maxdeep]='\0';
162         cout<<ans<<endl;
163         printf("%d\n",map[3][3]);
164     }
165     return 0;
166 }
167 
168 
169 
170                 
View Code

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值