现在的位置: 首页 > 综合 > 正文

【HDU】4939 Stupid Tower Defense 【dp】

2017年11月20日 ⁄ 综合 ⁄ 共 1191字 ⁄ 字号 评论关闭

传送门:【HDU】4939 Stupid Tower Defense

题目分析:稍微分析一下就可以知道红塔放在前面一定不会比放在后面更优,然后我们只需要对绿塔和蓝塔做一次dp。设dp[ i ][ j ]为前i个塔中有j个绿塔造成的最大伤害。那么可以得到这样的转移方程:

FOR ( i , 1 , n )
		FOR ( j , 1 , i ) {
			dp[i][j] = dp[i - 1][j - 1] + ( t + ( i - j ) * z ) * ( j - 1 ) * y ;
			if ( i - 1 >= j ) dp[i][j] = max ( dp[i][j] , dp[i - 1][j] + ( t + ( i - j - 1 ) * z ) * j * y ) ;
		}

第一条表示第i个位置放绿塔,( t + ( i - j ) * z ) * ( j - 1 ) * y为所有塔对位置i造成的伤害。

第二条表示第i个位置放蓝塔,( t + ( i - j - 1 ) * z ) * j * y为所有塔对位置i造成的伤害。

做完这个dp以后我们枚举所有的情况[ i , j ],对于[ i , j ]这种情况有:

damage[ i ][ j ]=dp[ i ][ j ] + ( n - i ) * ( ( t + ( i - j ) * z ) * ( x + j * y ) )的总伤害,( n - i ) * ( ( t + ( i - j ) * z ) * ( x + j * y ) )为x塔造成的伤害与前j个塔在之后造成的所有伤害的和。

答案即ans = max{damage[ i ][ j ] | 0 <= i <= n,0 <= j <= i }。

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )

typedef long long LL ;

const int MAXN = 1505 ;

LL dp[MAXN][MAXN] ;
LL n , x , y , z , t ;

void solve () {
	scanf ( "%I64d%I64d%I64d%I64d%I64d" , &n , &x , &y , &z , &t ) ;
	FOR ( i , 1 , n )
		FOR ( j , 1 , i ) {
			dp[i][j] = dp[i - 1][j - 1] + ( t + ( i - j ) * z ) * ( j - 1 ) * y ;
			if ( i - 1 >= j ) dp[i][j] = max ( dp[i][j] , dp[i - 1][j] + ( t + ( i - j - 1 ) * z ) * j * y ) ;
		}
	LL ans = 0 ;
	FOR ( i , 0 , n )
		FOR ( j , 0 , i )
			ans = max ( ans , dp[i][j] + ( n - i ) * ( ( t + ( i - j ) * z ) * ( x + j * y ) ) ) ;
	printf ( "%I64d\n" , ans ) ;
}

int main () {
	int T , cas = 0 ;
	scanf ( "%d" , &T ) ;
	while ( T -- ) {
		printf ( "Case #%d: " , ++ cas ) ;
		solve () ;
	}
	return 0 ;
}

抱歉!评论已关闭.