Stupid Tower DefenseTime Limit: 12000/6000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1908 Accepted Submission(s): 531
Problem Description
FSF is addicted to a stupid tower defense game. The goal of tower defense games is to try to stop enemies from crossing a map by building traps to slow them down and towers which shoot at them as they pass.
The map is a line, which has n unit length. We can build only one tower on each unit length. The enemy takes t seconds on each unit length. And there are 3 kinds of tower in this game: The red tower, the green tower and the blue tower. The red tower damage on the enemy x points per second when he passes through the tower. The green tower damage on the enemy y points per second after he passes through the tower. The blue tower let the enemy go slower than before (that is, the enemy takes more z second to pass an unit length, also, after he passes through the tower.) Of course, if you are already pass through m green towers, you should have got m*y damage per second. The same, if you are already pass through k blue towers, the enemy should have took t + k*z seconds every unit length. FSF now wants to know the maximum damage the enemy can get.
Input
There are multiply test cases.
The first line contains an integer T (T<=100), indicates the number of cases. Each test only contain 5 integers n, x, y, z, t (2<=n<=1500,0<=x, y, z<=60000,1<=t<=3)
Output
For each case, you should output "Case #C: " first, where C indicates the case number and counts from 1. Then output the answer. For each test only one line which have one integer, the answer to this question.
Sample Input
Sample Output
|
题意:敌军要经过一段n单元的路径。敌军每经过一个单元耗时t s,且我们可以在n单元路径上每单元设置一个塔。
红塔——敌军通过时,会对他们造成每秒x点伤害
绿塔——敌军通过后,会对他们造成每秒y点的持续伤害(直到走完长度为n的路径)
蓝塔——敌军通过后,会对他们减速,使得他们通过每单位长度的时间延长z s
问你对敌军造成的最大伤害。
思路:考虑把红塔放在最后面的情况,可能在后面放 0-n 个,在这个假设下求出最优解。
用dp[i][j]表示 在我们用过j个蓝塔的前提下 敌军到达第i个单元时 所付出的最大代价,显然0 <= j <= i。
则对dp[i][j],每秒伤害加成cost = (i-j) * y,通过每单元时间加成time = t + j * z。
那么最优解 = max(所有合法的dp[i][j] + (n - i) * (cost + x), dp[n][k]其中0 <= k <= n).
我们只需每次由dp[i][j]推出dp[i+1][j+1] 和 dp[i+1][j],然后对dp[i][j]的状态维护最大值。最后求出状态
dp[n][n] 和 dp[n][n-1],在(0 <= k <= n)上维护dp[n][k]最大值。
AC代码:
#include <cstdio> #include <cstring> #include <algorithm> #define MAXN 1500+1 #define LL long long using namespace std; LL dp[MAXN][MAXN]; int k = 1; void solve() { int n; LL x, y, z, t; scanf("%d%lld%lld%lld%lld", &n, &x, &y, &z, &t); memset(dp, 0, sizeof(dp)); LL ans = 0; for(int i = 0; i < n; i++) { for(int j = 0; j <= i; j++) { LL time = j * z + t, cost = (i - j) * y; dp[i+1][j+1] = max(dp[i+1][j+1], dp[i][j] + time * cost); dp[i+1][j] = max(dp[i+1][j], dp[i][j] + time * cost); ans = max(ans, dp[i][j] + (n-i) * (x + cost) * time); } if(i == n-1) for(int j = 0; j <= n; j++) ans = max(ans, dp[n][j]); } printf("Case #%d: %lld\n", k++, ans); } int main() { int t; scanf("%d", &t); while(t--){ solve(); } return 0; }