一开始读漏了很多细节,用递推写死活跑不出样例。
把题目中的细节列一下吧,状态方程很好推,改成记忆化搜索之后代码也很清晰。
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 ", 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 ", ans ); 106 107 } 108 return 0; 109 }