有3种塔,红塔可以在当前格子每秒造成x点伤害,绿塔可以在之后的格子每秒造成y点伤害,蓝塔可以使通过单位长度的时间增加z秒。问如何安排3种塔的顺序使得造成的伤害最大,输出最大伤害值
显然 红塔放在最后面是最优的,因此可以枚举i,红塔的位置就是i+1到n
那么只是看前面怎么选蓝和绿
dp[i][j]表示前面i个塔选j个蓝
我们考虑位置J放不放蓝塔时,从1到j的总伤害 //注意特判一下j=0,访问j-1会越界
__int64 tmp1=dp[i-1][j-1]+(i-j)*y*(t+(j-1)*z); //j is blue时,在第j造成的伤害 +前i-1的伤害
__int64 tmp2=dp[i-1][j]+(i-1-j)*y*(t+j*z); //j is green,在第j造成的伤害+前i-1的伤害
dp[i][j]=max(tmp1,tmp2);
然后前i个塔里选j个蓝的方案下,我们可以得到最终包括红塔的总伤害 为:
ans=max(ans,dp[i][j]+(n-i)*x*(t+j*z)+(n-i)*(t+j*z)*(i-j)*y);//总伤害,并更新ans
注意dp【i】【j】的i从1开始的话,至少选了1个非红塔,因此记得加上 全选红塔的情况
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <queue> #include <map> #include <set> #include <vector> #include <iostream> using namespace std; const double pi=acos(-1.0); double eps=0.000001; __int64 max(__int64 a,__int64 b) {return a<b?b:a;} __int64 dp[1505][1505]; int main() { int test; cin>>test; __int64 i,j; int cnt=1; __int64 x,y,z,t,n; while(test--) { scanf("%I64d%I64d%I64d%I64d%I64d",&n,&x,&y,&z,&t); memset(dp,0,sizeof(dp)); //dp[i][j] i+1到n是红,前i个里面放了j个蓝ta,i-j个绿 __int64 ans=t*x*n; for (i=1;i<=n;i++) { for (j=0;j<=i;j++) { if (j==0) dp[i][j]=dp[i-1][j]+(i-1-j)*y*t; else { __int64 tmp1=dp[i-1][j-1]+(i-j)*y*(t+(j-1)*z); //j is blue时,在第j造成的伤害 __int64 tmp2=dp[i-1][j]+(i-1-j)*y*(t+j*z); //j is green,在第j造成的伤害 dp[i][j]=max(tmp1,tmp2); } ans=max(ans,dp[i][j]+(n-i)*x*(t+j*z)+(n-i)*(t+j*z)*(i-j)*y);//总伤害,并更新ans } } printf("Case #%d: %I64d\n",cnt++,ans); } return 0; }