一开始读漏了很多细节,用递推写死活跑不出样例。
把题目中的细节列一下吧,状态方程很好推,改成记忆化搜索之后代码也很清晰。
1.蜜蜂需要到最高的塔去,最高的塔可能不止一个,抵达任意一个即可。
2.蜜蜂每次只能到达相邻的塔,满足的条件为横向移动距离<=W,下一个塔高 <= 上一个塔高 + H。
3.蜜蜂可以选择任意高度小于等于H的塔作为起始塔。
4.塔可以移动,但是塔之间的相对位置不变。只有最高的塔是不能移动的。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm> using namespace std; const int MAXN = ;
const int INF = << ; struct tower
{
int id;
int p, h;
}; tower Tw[MAXN];
int dp[MAXN][];
int cost[MAXN][]; // 把 tower[i] 移动到 位置j 所需要的代价
int N, H, W;
int maxH; bool cmp( tower a, tower b )
{
if ( a.p == b.p ) return a.id < b.id;
return a.p < b.p;
} int DpLeft( int cur, int addr, int preH )
{
if( cur == ) return INF; int &res = dp[cur][addr];
if ( res != - ) return res; if ( Tw[cur].h + H < preH ) return INF;
if ( Tw[cur].h <= H ) return cost[cur][addr]; res = INF;
for ( int j = addr; j >= addr - W && j > ; --j )
{
res = min( res, DpLeft( cur - , j, Tw[cur].h ) + cost[cur][addr] );
} //printf( "dp[%d][%d]=%d\n", cur, addr, res );
return res;
} int DpRight( int cur, int addr, int preH )
{
if ( cur > N ) return INF; int &res = dp[cur][addr];
if ( res != - ) return res; if ( Tw[cur].h + H < preH ) return res = INF;
if ( Tw[cur].h <= H ) return cost[cur][addr]; res = INF;
for ( int j = addr; j <= addr + W && j <= ; ++j )
res = min( res, DpRight( cur + , j, Tw[cur].h ) + cost[cur][addr] ); return res;
} int main()
{
//freopen( "in.txt", "r", stdin );
//freopen( "s.out", "w", stdout );
int T, cas = ;
scanf( "%d", &T );
while ( T-- )
{
scanf( "%d%d%d", &N, &H, &W );
maxH = -;
for ( int i = ; i <= N; ++i )
{
scanf( "%d%d", &Tw[i].p, &Tw[i].h );
Tw[i].id = i;
if ( Tw[i].h > maxH ) maxH = Tw[i].h;
} sort( Tw + , Tw + N + , cmp );
for ( int i = ; i <= N; ++i )
for ( int j = ; j <= ; ++j )
cost[i][j] = abs( Tw[i].p - j ) * Tw[i].h; int ans = INF; for ( int i = ; i <= N; ++i )
{
if ( Tw[i].h == maxH )
{
memset( dp, -, sizeof(dp) );
ans = min( ans, DpLeft( i, Tw[i].p, Tw[i].h ) ); memset( dp, -, sizeof(dp) );
ans = min( ans, DpRight( i, Tw[i].p, Tw[i].h ) ); }
} printf( "Case #%d: ", ++cas );
if ( ans >= INF ) puts("-1");
else printf( "%d\n", ans ); }
return ;
}