LA 6042 Bee Tower 记忆化搜索

一开始读漏了很多细节,用递推写死活跑不出样例。

把题目中的细节列一下吧,状态方程很好推,改成记忆化搜索之后代码也很清晰。

1.蜜蜂需要到最高的塔去,最高的塔可能不止一个,抵达任意一个即可。

2.蜜蜂每次只能到达相邻的塔,满足的条件为横向移动距离<=W,下一个塔高 <= 上一个塔高 + H。

3.蜜蜂可以选择任意高度小于等于H的塔作为起始塔。

4.塔可以移动,但是塔之间的相对位置不变只有最高的塔是不能移动的。

 

  1 #include <cstdio>

  2 #include <cstdlib>

  3 #include <cstring>

  4 #include <algorithm>

  5 

  6 using namespace std;

  7 

  8 const int MAXN = 60;

  9 const int INF = 1 << 30;

 10 

 11 struct tower

 12 {

 13     int id;

 14     int p, h;

 15 };

 16 

 17 tower Tw[MAXN];

 18 int dp[MAXN][510];

 19 int cost[MAXN][510];    // 把 tower[i] 移动到 位置j 所需要的代价

 20 int N, H, W;

 21 int maxH;

 22 

 23 bool cmp( tower a, tower b )

 24 {

 25     if ( a.p == b.p ) return a.id < b.id;

 26     return a.p < b.p;

 27 }

 28 

 29 int DpLeft( int cur, int addr, int preH )

 30 {

 31     if( cur == 0 ) return INF;

 32 

 33     int &res = dp[cur][addr];

 34     if ( res != -1 ) return res;

 35 

 36     if ( Tw[cur].h + H < preH ) return INF;

 37     if ( Tw[cur].h <= H ) return cost[cur][addr];

 38 

 39     res = INF;

 40     for ( int j = addr; j >= addr - W && j > 0; --j )

 41     {

 42         res = min( res, DpLeft( cur - 1, j, Tw[cur].h ) + cost[cur][addr] );

 43     }

 44 

 45     //printf( "dp[%d][%d]=%d\n", cur, addr, res );

 46     return res;

 47 }

 48 

 49 int DpRight( int cur, int addr, int preH )

 50 {

 51     if ( cur > N ) return INF;

 52 

 53     int &res = dp[cur][addr];

 54     if ( res != -1 ) return res;

 55 

 56     if ( Tw[cur].h + H < preH ) return res = INF;

 57     if ( Tw[cur].h <= H ) return cost[cur][addr];

 58 

 59     res = INF;

 60     for ( int j = addr; j <= addr + W && j <= 500; ++j )

 61         res = min( res, DpRight( cur + 1, j, Tw[cur].h ) + cost[cur][addr] );

 62 

 63     return res;

 64 }

 65 

 66 int main()

 67 {

 68     //freopen( "in.txt", "r", stdin );

 69     //freopen( "s.out", "w", stdout );

 70     int T, cas = 0;

 71     scanf( "%d", &T );

 72     while ( T-- )

 73     {

 74         scanf( "%d%d%d", &N, &H, &W );

 75         maxH = -1;

 76         for ( int i = 1; i <= N; ++i )

 77         {

 78             scanf( "%d%d", &Tw[i].p, &Tw[i].h );

 79             Tw[i].id = i;

 80             if ( Tw[i].h > maxH ) maxH = Tw[i].h;

 81         }

 82 

 83         sort( Tw + 1, Tw + N + 1, cmp );

 84         for ( int i = 1; i <= N; ++i )

 85             for ( int j = 1; j <= 500; ++j )

 86                 cost[i][j] = abs( Tw[i].p - j ) * Tw[i].h;

 87 

 88         int ans = INF;

 89 

 90         for ( int i = 1; i <= N; ++i )

 91         {

 92             if ( Tw[i].h == maxH )

 93             {

 94                 memset( dp, -1, sizeof(dp) );

 95                 ans = min( ans, DpLeft( i, Tw[i].p, Tw[i].h ) );

 96 

 97                 memset( dp, -1, sizeof(dp) );

 98                 ans = min( ans, DpRight( i, Tw[i].p, Tw[i].h ) );

 99 

100             }

101         }

102 

103         printf( "Case #%d: ", ++cas );

104         if ( ans >= INF ) puts("-1");

105         else printf( "%d\n", ans );

106 

107     }

108     return 0;

109 }

 

你可能感兴趣的:(搜索)