题意略。
思路:可以看出把红塔放在最后面是最好的,因为放在最后面是更有可能得到更多的时间从而导致伤害最高,然后只要判断前面的塔就行了。比赛的时候觉得把绿塔放在最前面蓝塔放中间。。事实证明这样是不靠谱的。。dp[i][j]代表前i个有j个是蓝塔,对于前面j个蓝塔任意放在任何地方都对后面不产生影响,因为后面的时间变为t+j*z,然后绿塔的伤害为(j-i)*y,所以要dp[i][j]最优,所以是由dp[i-1][j-1]和dp[i-1][j]递推得到。递推完这个后,再进行一次n^2的递推目的是加上后面红塔的伤害,然后求得最大值。总复杂度是o(n^2)。
AC代码:
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<ctime>
#include<string.h>
#include<string>
using namespace std;
#define ll __int64
ll dp[1505][1505];
int main()
{
#ifdef GLQ
freopen("input.txt","r",stdin);
// freopen("o.txt","w",stdout);
#endif // GLQ
int n,i,j,t,cas=1;
ll x,y,z;
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%I64d%I64d%I64d%d",&n,&x,&y,&z,&t);
memset(dp,0,sizeof(dp));
for(i = 1; i <= n; i++)
for(j = 0; j <= i; j++)
{
if(i == j) continue;
dp[i][j] = dp[i-1][j]+y*((ll)t+z*j)*(ll)(i-j-1);//绿塔
if(j >= 1)
dp[i][j] = max(dp[i][j],dp[i-1][j-1]+y*((ll)t+z*(j-1))*(ll)(i-j));//蓝塔
// cout<<i<<" "<<j<<" "<<dp[i][j]<<endl;
}
ll ans = n*t*x;
for(i = 1; i <= n; i++)
for(j = 0; j <= i; j++)
if(ans < dp[i][j] + (ll)(n-i)*(t+j*z)*(x+(i-j)*y))
{
ans = dp[i][j] + (ll)(n-i)*(t+j*z)*(x+(i-j)*y);
// cout<<ans<<endl;
}
printf("Case #%d: %I64d\n",cas++,ans);
}
return 0;
}