zoukankan      html  css  js  c++  java
  • HDU 4939 Stupid Tower Defense 简单DP

    题意:

      地图为长为n个单位长度的直线,每通过一个单位长度需要t秒。

      有3种塔,红塔可以在当前格子每秒造成x点伤害,绿塔可以在之后格子造成y点伤害,蓝塔可以使通过单位长度的时间增加z秒。

      让你安排塔的排列是造成的伤害最大。

    思路:

      最开始想到dp,状态dp[i][r][g][b]表示:假设前i格放了r个红塔、g个绿塔和b个蓝塔,枚举第i+1格放什么。

      因为长度最大为1500,所以如果这样开状态的话,需要1500^4的空间,这显然是开不下的。

      后来想到,一种塔的数量可以表示成总数减去另外两种塔的数量,这样的话,就可以减掉一维,变成dp[i][g][b],还是会超空间。

      然后想到,红塔只在当前格子有效,所以不用记录有多少红塔,只需要知道有多少绿塔和蓝塔就好了,也不用记录当前是第几格。所以状态变成了dp[g][b]。

      但是,这样子时间复杂度仍然是n^3的,会超时。

      可以证明,如果存在红塔,放在后面一定比放在前面更优。所以,只需要dp前面有g个绿塔和b个蓝塔时候造成的最大伤害,然后在求解的时候计算出后面全是红塔。 所以,时间复杂度也变成了n^2。这样子就可以解了。

    代码:

      

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <cmath>
     6 #include <algorithm>
     7 #include <string>
     8 #include <queue>
     9 #include <stack>
    10 #include <vector>
    11 #include <map>
    12 #include <set>
    13 #include <functional>
    14 #include <time.h>
    15 
    16 using namespace std;
    17 
    18 typedef __int64 ll;
    19 
    20 const int INF = 1<<30;
    21 const int MAXN = 1555;
    22 
    23 ll dp[MAXN][MAXN]; //dp[i][j]: 前面i+j个塔中,有i个green,j个blue
    24 ll n, x, y, z, t;
    25 
    26 void solve() {
    27     scanf("%I64d%I64d%I64d%I64d%I64d", &n, &x, &y, &z, &t);
    28 
    29     memset(dp, 0, sizeof(dp));
    30     for (int i = 0; i < n; i++)
    31         for (int j = 0; j+i < n; j++) {
    32             dp[i+1][j] = max(dp[i+1][j], dp[i][j]+(i*y)*(t+j*z));
    33             dp[i][j+1] = max(dp[i][j+1], dp[i][j]+(i*y)*(t+j*z));
    34         }
    35 
    36     ll ans = 0;
    37     for (int i = 0; i <= n; i++)
    38         for (int j = 0; i+j <= n; j++)
    39             ans = max(ans, dp[i][j]+((n-i-j)*(x+i*y))*(t+z*j));
    40 
    41     printf("%I64d
    ", ans);
    42 }
    43 
    44 int main() {
    45     #ifdef Phantom01
    46         freopen("HDU4939.txt", "r", stdin);
    47     #endif //Phantom01
    48 
    49     int T;
    50     scanf("%d", &T);
    51     for (int i = 1; i <= T; i++) {
    52         printf("Case #%d: ", i);
    53         solve();
    54     }
    55 
    56     return 0;
    57 }
    View Code
  • 相关阅读:
    NOKIA自己掌控的新的智能手机系统ASHA
    NOKIA自己掌控的新的智能手机系统ASHA
    双系统启动菜单修复工具(NTBootAutofix)v2.5.7 绿色版
    双系统启动菜单修复工具(NTBootAutofix)v2.5.7 绿色版
    如何用ghost安装双系统(WinXP+Win7)
    摄影还能这么玩!Jamie Beck创意GIF摄影
    线程知识结构概览
    window多线程操作文件
    多线程内存的表现形式
    进程的调度的理解
  • 原文地址:https://www.cnblogs.com/Phantom01/p/3909427.html
Copyright © 2011-2022 走看看