这些天一直在搞搜索, 从Dancing Links 到 A*,IDA*, 之前把Dancing Links刷了几道,这两天在搞 A*,和IDA*, 目前终于把hdu上的几道IDA*刷完了。。

参考大牛博客:http://www.cnblogs.com/ambition/archive/2011/07/25/search_plus.html

HDU 1667 The Rotation Game 

状态很多,IDA*是必须的, 每次可以移动八个方向,  可以构造h()=8-max(1,2,3);  max(1,2,3)表示中间的八个位置中出现最多的数的个数。 因为每次

操作只能改变中间8个中的一个,所以可以这样构造启发式函数。

View Code
  1 # include<stdio.h>
2 # include<string.h>
3 # include<time.h>
4 int map[8][8],deep;
5 char visit[100];
6 void roA()
7 {
8 int i,temp;
9 temp=map[1][3];
10 for(i=2;i<=7;i++)
11 map[i-1][3]=map[i][3];
12 map[7][3]=temp;
13 }
14 void roB()
15 {
16 int i,temp;
17 temp=map[1][5];
18 for(i=2;i<=7;i++)
19 map[i-1][5]=map[i][5];
20 map[7][5]=temp;
21 }
22 void roC()
23 {
24 int i,temp;
25 temp=map[3][7];
26 for(i=6;i>=1;i--)
27 map[3][i+1]=map[3][i];
28 map[3][1]=temp;
29 }
30 void roD()
31 {
32 int i,temp;
33 temp=map[5][7];
34 for(i=6;i>=1;i--)
35 map[5][i+1]=map[5][i];
36 map[5][1]=temp;
37 }
38 void roE()
39 {
40 int i,temp;
41 temp=map[7][5];
42 for(i=6;i>=1;i--)
43 map[i+1][5]=map[i][5];
44 map[1][5]=temp;
45 }
46 void roF()
47 {
48 int i,temp;
49 temp=map[7][3];
50 for(i=6;i>=1;i--)
51 map[i+1][3]=map[i][3];
52 map[1][3]=temp;
53 }
54 void roG()
55 {
56 int i,temp;
57 temp=map[5][1];
58 for(i=2;i<=7;i++)
59 map[5][i-1]=map[5][i];
60 map[5][7]=temp;
61 }
62 void roH()
63 {
64 int i,temp;
65 temp=map[3][1];
66 for(i=2;i<=7;i++)
67 map[3][i-1]=map[3][i];
68 map[3][7]=temp;
69 }
70 int max(int a,int b)
71 {
72 return a>b?a:b;
73 }
74 int h()
75 {
76 int count[4],i;
77 count[1]=count[2]=count[3]=0;
78 for(i=3;i<=5;i++)
79 {
80 count[map[3][i]]++;
81 count[map[5][i]]++;
82 }
83 count[map[4][3]]++;
84 count[map[4][5]]++;
85 return 8-max(max(count[1],count[2]),count[3]);
86 }
87 bool check(){
88 if(map[3][3]!=map[3][4]) return false;
89 if(map[3][3]!=map[3][5]) return false;
90 if(map[3][3]!=map[4][3]) return false;
91 if(map[3][3]!=map[5][3]) return false;
92 if(map[3][3]!=map[5][4]) return false;
93 if(map[3][3]!=map[5][5]) return false;
94 if(map[3][3]!=map[4][5]) return false;
95 return true;
96 }
97 bool dfs(int d)
98 {
99 int ans;
100 //if(d==deep) return check();
101 ans=h();
102 if(ans==0) return 1;
103 if(d+ans>deep) return 0;
104
105
106 roA();
107 visit[d]='A';
108 if(dfs(d+1)) return 1;
109 roF();
110
111
112 roB();
113 visit[d]='B';
114 if(dfs(d+1)) return 1;
115 roE();
116
117
118 roC();
119 visit[d]='C';
120 if(dfs(d+1)) return 1;
121 roH();
122
123 roD();
124 visit[d]='D';
125 if(dfs(d+1)) return 1;
126 roG();
127
128
129 roE();
130 visit[d]='E';
131 if(dfs(d+1)) return 1;
132 roB();
133
134
135 roF();
136 visit[d]='F';
137 if(dfs(d+1)) return 1;
138 roA();
139
140
141 roG();
142 visit[d]='G';
143 if(dfs(d+1)) return 1;
144 roD();
145
146
147 roH();
148 visit[d]='H';
149 if(dfs(d+1)) return 1;
150 roC();
151
152
153 return 0;
154
155
156 }
157 int main()
158 {
159 int i,t1,t2;
160 /*t1=clock();
161 freopen("1667.in","r",stdin);*/
162 while(scanf("%d",&map[1][3])!=EOF && map[1][3])
163 {
164 scanf("%d%d%d",&map[1][5],&map[2][3],&map[2][5]);
165 for(i=1;i<=7;i++)
166 scanf("%d",&map[3][i]);
167 scanf("%d%d",&map[4][3],&map[4][5]);
168 for(i=1;i<=7;i++)
169 scanf("%d",&map[5][i]);
170 scanf("%d%d%d%d",&map[6][3],&map[6][5],&map[7][3],&map[7][5]);
171 deep=0;
172 while(1)
173 {
174 if(dfs(0)) break;
175 deep++;
176 }
177 if(deep==0) {printf("No moves needed\n");printf("%d\n",map[3][3]);continue;}
178 for(i=0;i<deep;i++)
179 printf("%c",visit[i]);
180 printf("\n");
181 printf("%d\n",map[3][3]);
182 /*t2=clock();
183 printf("%d\n\n",t2-t1);*/
184 }
185 return 0;
186 }

hdu 2234 无题I

和上面那题基本上类似,h()函数稍微有一点变化。 对于h(): 可以考虑把每一行上的数转化成相同的,或者把每一列上的数字转化成相同的,二者取最小值。

例如:  1 1 3  2

           2 4 4 2

           3 3 1 4

           1 2 3 4

如果把这个矩阵转化成行相同的话需要的操作:第一行 至少要2次,第二行也是2次, 第三行是2次,第四行是3次,  所以把矩阵转化成行相同至少要3次。

代码:

View Code
  1 # include<stdio.h>
2 # include<string.h>
3 int map[5][5],deep;
4 int max(int a,int b)
5 {
6 return a>b?a:b;
7 }
8 int h()
9 {
10 int num1,num2,count[5],ans,i,j;
11 num1=0;
12 for(i=1;i<=4;i++)
13 {
14 memset(count,0,sizeof(count));
15 for(j=1;j<=4;j++)
16 count[map[i][j]]++;
17 count[1]=max(count[1],count[2]);
18 ans=max(max(count[1],count[3]),count[4]);
19 num1=max(num1,4-ans);
20 }
21 num2=0;
22 for(j=1;j<=4;j++)
23 {
24 memset(count,0,sizeof(count));
25 for(i=1;i<=4;i++)
26 count[map[i][j]]++;
27 count[1]=max(count[1],count[2]);
28 ans=max(max(count[1],count[3]),count[4]);
29 num2=max(num2,4-ans);
30 }
31 return num1<num2?num1:num2;
32 }
33 bool dfs(int d)
34 {
35 int ans,i,j,temp;
36 ans=h();
37 if(ans==0) return 1;
38 if(ans+d>deep) return 0;
39 for(i=1;i<=4;i++)
40 {
41 temp=map[i][1];
42 for(j=2;j<=4;j++)
43 map[i][j-1]=map[i][j];
44 map[i][4]=temp;
45 if(dfs(d+1)) return 1;
46 temp=map[i][4];
47 for(j=3;j>=1;j--)
48 map[i][j+1]=map[i][j];
49 map[i][1]=temp;
50 }
51 for(i=1;i<=4;i++)
52 {
53 temp=map[i][4];
54 for(j=3;j>=1;j--)
55 map[i][j+1]=map[i][j];
56 map[i][1]=temp;
57 if(dfs(d+1)) return 1;
58 temp=map[i][1];
59 for(j=2;j<=4;j++)
60 map[i][j-1]=map[i][j];
61 map[i][4]=temp;
62 }
63 for(j=1;j<=4;j++)
64 {
65 temp=map[1][j];
66 for(i=2;i<=4;i++)
67 map[i-1][j]=map[i][j];
68 map[4][j]=temp;
69 if(dfs(d+1)) return 1;
70 temp=map[4][j];
71 for(i=3;i>=1;i--)
72 map[i+1][j]=map[i][j];
73 map[1][j]=temp;
74 }
75 for(j=1;j<=4;j++)
76 {
77 temp=map[4][j];
78 for(i=3;i>=1;i--)
79 map[i+1][j]=map[i][j];
80 map[1][j]=temp;
81 if(dfs(d+1)) return 1;
82 temp=map[1][j];
83 for(i=2;i<=4;i++)
84 map[i-1][j]=map[i][j];
85 map[4][j]=temp;
86 }
87 return 0;
88 }
89 int main()
90 {
91 int i,j,ncase;
92 scanf("%d",&ncase);
93 while(ncase--)
94 {
95 for(i=1;i<=4;i++)
96 for(j=1;j<=4;j++)
97 scanf("%d",&map[i][j]);
98 deep=0;
99 while(1)
100 {
101 if(dfs(0)) break;
102 deep++;
103 if(deep>5) break;
104 }
105 if(deep>5) printf("-1\n");
106 else printf("%d\n",deep);
107 }
108 return 0;
109 }

hdu   1560  DNA sequence

这个题我刚开始的想法有些错误,我是给主串每次操作增加一个字符,然后判断每一个字符串在主串中已出现多少字符,还需要在添加多少字符,

然后直到所有的字符串都是主串的子串。。

因为这样字符串的长度没有减少,每次查找都很浪费时间,导致最后TLE。。

可以反过来想,每次给主串增加一个字符和字符串的最后一位比较,如果相同,这个字符串的长度减一, 这样无需再像刚才那样查找,然后这个主串也无需记录。。

构造h()为当前所有字符串中长度最长的。

code:

View Code
 1 # include<stdio.h>
2 # include<string.h>
3 # include<stdlib.h>
4 char str[10][6],st[60];
5 int n,Len,deep;
6 char dir[]="ACGT";
7 int max(int a,int b)
8 {
9 return a>b?a:b;
10 }
11 int len[10];
12 int h()
13 {
14 int i,ans;
15 ans=0;
16 for(i=0;i<n;i++)
17 ans=max(ans,len[i]);
18 return ans;
19 }
20 bool dfs(int d)
21 {
22 int i,ans,tlen[10],flag,j;
23 ans=h();
24 if(ans==0) return 1;
25 if(ans+d>deep) return 0;
26 for(i=0;i<4;i++)
27 {
28 flag=0;
29 for(j=0;j<n;j++)
30 {
31 tlen[j]=len[j];
32 if(!len[j]) continue;
33 if(str[j][len[j]-1]==dir[i])
34 {
35 flag=1;
36 len[j]--;
37 }
38 }
39 if(flag)
40 {
41 if(dfs(d+1)) return 1;
42 }
43 for(j=0;j<n;j++)
44 len[j]=tlen[j];
45 }
46 return 0;
47 }
48 int main()
49 {
50 int i,ncase;
51 scanf("%d",&ncase);
52 while(ncase--)
53 {
54 scanf("%d",&n);
55 for(i=0;i<n;i++)
56 {
57 scanf("%s",str[i]);
58 len[i]=strlen(str[i]);
59 }
60 deep=0;
61 while(1)
62 {
63 if(dfs(0)) break;
64 deep++;
65 }
66 printf("%d\n",deep);
67 }
68 return 0;
69 }

hdu 1813  Escape from Tetris

这个题要记得先用广搜算出每一个‘0’字符的位置逃脱需要最少的操作数。。

然后就可以模拟搜索了,,h()为当 前 每一个的节点到逃脱所需要的时间的最大值,因为刚才已经计算出每一个能走的位置逃脱的最少花费,这里可以直接调用。

有一种状态向另外一种状态转化,之后再恢复这种状态, 细节问题,这一点需要注意。。

hdu 2918  Tobo or not Tobo

做过前面几道,这一题应该算是比较简单的了,每一次也是可以有八种操作, 因为每一次操作只能改变四个点的位置,所有可以构造h()=(count+1)/4;

 count表示不在对应位置上的点的个数。

View Code
  1 # include<stdio.h>
2 # include<string.h>
3 int deep,n;
4 int map[4][4];
5
6 int ABS(int x)
7 {
8 return x<0?(-x):x;
9 }
10 int max(int a,int b)
11 {
12 return a>b?a:b;
13 }
14 int h1()
15 {
16 int i,j,count=0;
17 for(i=1;i<=3;i++)
18 for(j=1;j<=3;j++)
19 if(map[i][j]!=(i-1)*3+j) count++;
20 return (count+3)/4;
21 }
22 int h2()
23 {
24 int i,j,ans,endx,endy;
25 ans=0;
26 for(i=1;i<=3;i++)
27 {
28 for(j=1;j<=3;j++)
29 {
30 endx=(map[i][j]+2)/3;
31 endy=(map[i][j]-1)%3+1;
32 ans=max(ans,ABS(endx-i)+ABS(endy-j));
33 }
34 }
35 return (ans+1)/2;
36 }
37 void CoA()
38 {
39 int temp;
40 temp=map[1][1];
41 map[1][1]=map[2][1];
42 map[2][1]=map[2][2];
43 map[2][2]=map[1][2];
44 map[1][2]=temp;
45 }
46 void AoA()
47 {
48 int temp;
49 temp=map[1][1];
50 map[1][1]=map[1][2];
51 map[1][2]=map[2][2];
52 map[2][2]=map[2][1];
53 map[2][1]=temp;
54 }
55 void CoB()
56 {
57 int temp;
58 temp=map[1][2];
59 map[1][2]=map[2][2];
60 map[2][2]=map[2][3];
61 map[2][3]=map[1][3];
62 map[1][3]=temp;
63 }
64 void AoB()
65 {
66 int temp;
67 temp=map[1][2];
68 map[1][2]=map[1][3];
69 map[1][3]=map[2][3];
70 map[2][3]=map[2][2];
71 map[2][2]=temp;
72 }
73 void CoC()
74 {
75 int temp;
76 temp=map[2][1];
77 map[2][1]=map[3][1];
78 map[3][1]=map[3][2];
79 map[3][2]=map[2][2];
80 map[2][2]=temp;
81 }
82 void AoC()
83 {
84 int temp;
85 temp=map[2][1];
86 map[2][1]=map[2][2];
87 map[2][2]=map[3][2];
88 map[3][2]=map[3][1];
89 map[3][1]=temp;
90 }
91 void CoD()
92 {
93 int temp;
94 temp=map[2][2];
95 map[2][2]=map[3][2];
96 map[3][2]=map[3][3];
97 map[3][3]=map[2][3];
98 map[2][3]=temp;
99 }
100 void AoD()
101 {
102 int temp;
103 temp=map[2][2];
104 map[2][2]=map[2][3];
105 map[2][3]=map[3][3];
106 map[3][3]=map[3][2];
107 map[3][2]=temp;
108 }
109 bool dfs(int d)
110 {
111 int ans;
112 //ans=max(h1(),h2());
113 ans=h1();
114 //ans=h2();
115 if(ans==0) return 1;
116 if(ans+d>deep || ans+d>n) return 0;
117 CoA();
118 if(dfs(d+1)) return 1;
119 AoA();
120
121 AoA();
122 if(dfs(d+1)) return 1;
123 CoA();
124
125 CoB();
126 if(dfs(d+1)) return 1;
127 AoB();
128
129 AoB();
130 if(dfs(d+1)) return 1;
131 CoB();
132
133 CoC();
134 if(dfs(d+1)) return 1;
135 AoC();
136
137 AoC();
138 if(dfs(d+1)) return 1;
139 CoC();
140
141 CoD();
142 if(dfs(d+1)) return 1;
143 AoD();
144
145 AoD();
146 if(dfs(d+1)) return 1;
147 CoD();
148
149 return 0;
150 }
151 void in(int & val){
152 char in=getchar();
153 while(in<=32) in=getchar();
154 val=(in=='0');
155 }
156 int main()
157 {
158 int i,j,ncase=0;
159 __int64 ans;
160 while(scanf("%I64d",&ans)!=EOF)
161 {
162 if(ans==0) break;
163 for(i=3;i>=1;i--)
164 for(j=3;j>=1;j--)
165 {
166 map[i][j]=ans%10;
167 ans/=10;
168 }
169 n=ans%10;
170 ncase++;
171 deep=0;
172 while(1)
173 {
174 if(dfs(0)) break;
175 deep++;
176 if(deep>n) break;
177 }
178 printf("%d. ",ncase);
179 if(deep<=n) printf("%d\n",deep);
180 else printf("-1\n");
181 }
182 return 0;
183 }

hdu 3459  Rubik 2×2×2

这个题难是不难, 不过输入的时候很恶心,不知是我英语不好没读懂,还是题目没描述好。。

因为有一个方格是固定的,所以可以根据这一点构造h函数。

判断在什么情况下,必须按x旋转; 在什么情况下,必须按y旋转;在什么情况下,必须按z旋转。

code:

View Code
  1 # include<stdio.h>
2 # include<string.h>
3 int deep;
4 char mapU[3][3];
5 char mapL[3][3];
6 char mapF[3][3];
7 char mapR[3][3];
8 char mapB[3][3];
9 char mapD[3][3];
10 char visit[105];
11 void CoX()
12 {
13 char temp1,temp2;
14 temp1=mapU[1][2];
15 temp2=mapU[2][2];
16 mapU[2][2]=mapB[1][1];
17 mapU[1][2]=mapB[2][1];
18 mapB[1][1]=mapD[1][2];
19 mapB[2][1]=mapD[2][2];
20 mapD[1][2]=mapF[2][2];
21 mapD[2][2]=mapF[1][2];
22 mapF[1][2]=temp1;
23 mapF[2][2]=temp2;
24 char temp;
25 temp=mapR[1][1];
26 mapR[1][1]=mapR[1][2];
27 mapR[1][2]=mapR[2][2];
28 mapR[2][2]=mapR[2][1];
29 mapR[2][1]=temp;
30 }
31 void CoY()
32 {
33 char temp1,temp2;
34 temp1=mapF[1][1];
35 temp2=mapF[1][2];
36 mapF[1][1]=mapL[1][1];
37 mapF[1][2]=mapL[1][2];
38 mapL[1][1]=mapB[1][1];
39 mapL[1][2]=mapB[1][2];
40 mapB[1][1]=mapR[1][1];
41 mapB[1][2]=mapR[1][2];
42 mapR[1][1]=temp1;
43 mapR[1][2]=temp2;
44 char temp;
45 temp=mapU[1][1];
46 mapU[1][1]=mapU[1][2];
47 mapU[1][2]=mapU[2][2];
48 mapU[2][2]=mapU[2][1];
49 mapU[2][1]=temp;
50 }
51 void CoZ()
52 {
53 char temp1,temp2;
54 temp1=mapR[1][1];
55 temp2=mapR[2][1];
56 mapR[1][1]=mapD[2][2];
57 mapR[2][1]=mapD[2][1];
58 mapD[2][2]=mapL[2][2];
59 mapD[2][1]=mapL[1][2];
60 mapL[1][2]=mapU[2][2];
61 mapL[2][2]=mapU[2][1];
62 mapU[2][2]=temp2;
63 mapU[2][1]=temp1;
64 char temp;
65 temp=mapF[1][1];
66 mapF[1][1]=mapF[1][2];
67 mapF[1][2]=mapF[2][2];
68 mapF[2][2]=mapF[2][1];
69 mapF[2][1]=temp;
70 }
71 int h()
72 {
73 int count=0;
74 if(mapD[1][2]!=mapD[1][1] || mapB[2][2]!=mapB[2][1]) count++;//只有经过x轴的旋转才能改变
75 if(mapB[2][2]!=mapB[1][2] || mapL[2][1]!=mapL[1][1]) count++;
76 if(mapD[1][1]!=mapD[2][1] || mapL[2][1]!=mapL[2][2]) count++;
77 return count;
78 }
79 bool check()
80 {
81 if(!(mapF[1][1]==mapF[1][2] && mapF[1][1]==mapF[2][1] && mapF[1][1]==mapF[2][2])) return 0;
82 if(!(mapU[1][1]==mapU[1][2] && mapU[1][1]==mapU[2][1] && mapU[1][1]==mapU[2][2])) return 0;
83 if(!(mapD[1][1]==mapD[1][2] && mapD[1][1]==mapD[2][1] && mapD[1][1]==mapD[2][2])) return 0;
84 if(!(mapB[1][1]==mapB[1][2] && mapB[1][1]==mapB[2][1] && mapB[1][1]==mapB[2][2])) return 0;
85 if(!(mapL[1][1]==mapL[1][2] && mapL[1][1]==mapL[2][1] && mapL[1][1]==mapL[2][2])) return 0;
86 if(!(mapR[1][1]==mapR[1][2] && mapR[1][1]==mapR[2][1] && mapR[1][1]==mapR[2][2])) return 0;
87 return 1;
88 }
89 bool dfs(int d)
90 {
91 int ans;
92 ans=h();
93 if(d+ans>deep && deep-d<=3) return 0;
94 if(d==deep) return check();
95
96 CoX();
97 visit[d]='X';
98 if(dfs(d+1)) return 1;
99 CoX();CoX();CoX();
100
101 CoY();
102 visit[d]='Y';
103 if(dfs(d+1)) return 1;
104 CoY();CoY();CoY();
105
106 CoZ();
107 visit[d]='Z';
108 if(dfs(d+1)) return 1;
109 CoZ();CoZ();CoZ();
110
111 return 0;
112 }
113 int main()
114 {
115 int i;
116 char str[7][9];
117 while(scanf("%s",str[0])!=EOF)
118 {
119 for(i=1;i<6;i++)
120 scanf("%s",str[i]);
121 if(str[0][2]=='.') break;
122 mapU[1][1]=str[0][2];
123 mapU[1][2]=str[0][3];
124 mapU[2][1]=str[1][2];
125 mapU[2][2]=str[1][3];
126
127 mapL[1][1]=str[2][0];
128 mapL[1][2]=str[2][1];
129
130 mapF[1][1]=str[2][2];
131 mapF[1][2]=str[2][3];
132
133 mapR[1][1]=str[2][4];
134 mapR[1][2]=str[2][5];
135
136 mapB[1][1]=str[2][6];
137 mapB[1][2]=str[2][7];
138
139 mapL[2][1]=str[3][0];
140 mapL[2][2]=str[3][1];
141
142 mapF[2][1]=str[3][2];
143 mapF[2][2]=str[3][3];
144
145 mapR[2][1]=str[3][4];
146 mapR[2][2]=str[3][5];
147
148 mapB[2][1]=str[3][6];
149 mapB[2][2]=str[3][7];
150
151 mapD[1][1]=str[5][2];
152 mapD[1][2]=str[5][3];
153
154 mapD[2][1]=str[4][2];
155 mapD[2][2]=str[4][3];
156
157 deep=0;
158 while(1)
159 {
160 if(dfs(0)) break;
161 deep++;
162 }
163 for(i=0;i<deep;i++)
164 printf("%c",visit[i]);
165 printf("\n");
166 }
167 return 0;
168 }
posted on 2011-08-14 11:28  奋斗青春  阅读(344)  评论(0编辑  收藏  举报