POJ 3460 Booksort

题目链接:http://poj.org/problem?id=3460

题意:有一些高度不等的书,可以一次取出一摞相对顺序不变的书插入任意位置,问最少多少次操作才能使书的高度递增有序。

IDA*,刘汝佳黑书P169的例题,经典题目,启发函数的设计十分巧妙。

以“h(s)=后继书本高度正确的书本个数”为估价函数,假设每次把一摞书本S从P1后面移动到P2后面,只有P1,S1的最后一本,P2三本书的后继有变化,h每次最多减少3,令h'=h(s)/3作为估价函数值,则每次h最多减少1。

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 
 6 const int MAXN = 20;
 7 
 8 int N, limit;
 9 int book[MAXN];
10 bool find;
11 
12 int min( int a, int b )
13 {
14     return a < b ? a : b;
15 }
16 
17 int h( int *a )
18 {
19     int cnt = 0;
20     if ( a[0] != 1 ) ++cnt;
21     if ( a[N - 1] != N ) ++cnt;
22     for ( int i = 1; i < N - 1; ++i )
23             if ( a[i] + 1 != a[i + 1] ) ++cnt;
24     return ceil( cnt / 3.0 );
25 }
26 
27 void chuli( int st, int mid, int ed )
28 {
29     int temp[MAXN];
30     for ( int i = mid + 1; i <= ed; ++i )
31         temp[i] = book[i];
32     for ( int i = mid, j = ed; i >= st; --i, --j )
33         book[j] = book[i];
34     for ( int i = st, j = mid + 1; j <= ed; ++i, ++j )
35         book[i] = temp[j];
36     return;
37 }
38 
39 int DFS( int dv )
40 {
41     int temp[MAXN];
42     int hv = h( book );
43     if ( hv + dv > limit ) return hv + dv;
44     if ( hv == 0 )
45     {
46         find = true;
47         return dv;
48     }
49 
50     int next_limit = 1e5;
51 
52     for ( int i = 0; i < N - 1; ++i )
53     for ( int j = i + 1; j < N; ++j )
54     for ( int k = i; k < j; ++k )
55     {
56         for ( int x = 0; x < N; ++x )
57             temp[x] = book[x];
58 
59         chuli( i, k, j );
60 
61         int new_limit = DFS( dv + 1 );
62 
63         if ( find ) return new_limit;
64 
65         next_limit = min( next_limit, new_limit );
66         for ( int x = 0; x < N; ++x )
67             book[x] = temp[x];
68     }
69 
70     return next_limit;
71 }
72 
73 void IDA_Star()
74 {
75     find = false;
76     limit = h( book );
77     while ( !find && limit < 5 )
78         limit = DFS( 0 );
79     return;
80 }
81 
82 int main()
83 {
84     int T;
85     scanf( "%d", &T );
86     while ( T-- )
87     {
88         scanf( "%d", &N );
89         for ( int i = 0; i < N; ++i )
90             scanf( "%d", &book[i] );
91 
92         IDA_Star();
93         if ( find ) printf( "%d\n", limit );
94         else puts("5 or more");
95     }
96     return 0;
97 }

 

posted @ 2013-04-25 23:01  冰鸮  阅读(440)  评论(0)    收藏  举报