zoukankan      html  css  js  c++  java
  • hdu 4939 Stupid Tower Defense 动态规划

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4939

    塔防游戏 红塔绿塔蓝塔

    当年我队友在不知道红塔必须放最后这个结论的情况下把这道题做出来了现在我细思恐极 仰慕至极Orz

    写出来不是很难的题目 但是仔细想想 还是有很多值得推敲的地方

    下面证明一下这个“常识”

    反证法

    a.如果得到一个最优解 然后在这个最优解中有一个红塔在一个绿塔前面 那么把这两个塔交换一下位置 必定可以得到一个更优的解 与假设的“当前是最优解”矛盾

    b.如果得到一个最优解 然后在这个最优解中有一个红塔在一个蓝塔前面 那么把这两个塔交换一下位置 必定可以得到一个更优的解 与假设的“当前是最优解”矛盾

    所以 在最优解中 红塔一定是在最后的

    此题表意不清 注意绿塔和蓝塔都是当前格不生效、走过以后才生效的

    用dp[i][j]表示前i个塔中有j个蓝塔(并且假定后面全是红塔)时 前i格能造成的总的最大伤害 

    【如果不知道红塔在最后这个结论 那么可能就会变成dp[i][j][k]来表示前i格的状态 这时候会MLE】

    【可是我队友居然用dp1[i][j]和dp2[i][k]两个数组解决了这个矛盾 我也是吓尿了】

    动态规划的意义在于 只需要枚举三种塔各自的数量 而不用枚举具体的摆法

    当j==0时 dp[i][j]可以直接算

    当j!=0时 dp[i][j]仅与dp[i-1][j-1]和dp[i-1][j]有关 

    算出dp[i][j]后再加上后面(n-i)格的伤害即可得到当前摆法的最大伤害 不断更新最大值

    可以这样递推的原因在于 假如已经求得dp[i-1][?]的最优 那么接下来在求dp[i][?]的最优时 不可能打乱前(i-1)格的摆法

    不管第i格是放什么塔,它的结果仅与前面的各塔总数有关,而与前面摆法无关

    注意要算全是红塔的情况 Orz 

    像我这种写法就要把ans初始化为全是红塔的结果

    #include <cstdio>
    #include <cstdlib>
    #include <ctime>
    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <stack>
    #include <set>
    #include <queue>
    #include <vector>
    
    using namespace std;
    
    typedef long long ll;
    
    const int maxn = 1510;
    
    ll dp[maxn][maxn];
    
    int main()
    {
        //freopen("in.txt", "r", stdin);
    
        int T;
        scanf("%d", &T);
        for(int kase = 1; kase <= T; kase++)
        {
            ll n, x, y, z, t;
            scanf("%I64d%I64d%I64d%I64d%I64d", &n, &x, &y, &z, &t);
    
            ll ans = n * t * x;
    
            for(ll i = 1; i <= n; i++)
            {
                for(ll j = 0; j <= i; j++)
                {
                    if(j == 0)
                        dp[i][0] = dp[i-1][0] + y * (i-1) * t;
                    else
                        dp[i][j] = max(dp[i-1][j-1] + y * (i-j) * (t+z*(j-1)), dp[i-1][j] + y * (i-j-1) * (t+z*j));
    
                    ll tmp = dp[i][j] + (x + y*(i-j)) * (n-i) * (t + z*j);
                    if(tmp > ans)
                        ans = tmp;
                }
            }
    
            printf("Case #%d: %I64d
    ", kase, ans);
        }
        return 0;
    }
  • 相关阅读:
    C#根据html生成PDF
    Oracle 存储过程异常处理
    Oracle事务之一:锁和隔离
    跨域解决方案一:使用CORS实现跨域
    AJAX POST&跨域 解决方案
    使用 jQuery Deferred 和 Promise 创建响应式应用程序
    jQuery:多个AJAX/JSON请求对应单个回调并行加载
    解决td标签上的position:relative属性在各浏览器中的兼容性问题
    盘点8种CSS实现垂直居中水平居中的绝对定位居中技术
    JQuery-UI Dialog下使用服务器端按钮失效
  • 原文地址:https://www.cnblogs.com/dishu/p/4295403.html
Copyright © 2011-2022 走看看