• 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;
    }
  • 相关阅读:
    秒杀多线程第二篇 多线程第一次亲密接触 CreateThread与_beginthreadex本质区别(续)
    秒杀多线程第二篇 多线程第一次亲密接触 CreateThread与_beginthreadex本质区别
    秒杀多线程第一篇 多线程笔试面试题汇总
    多线程---handlerthread
    AsyncTask使用须知
    Intent
    字典树 trie
    倒排索引
    百度大搜 算法的实习
    学习路径
  • 原文地址:https://www.cnblogs.com/dishu/p/4295403.html
Copyright © 2020-2023  润新知