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;
    }
  • 相关阅读:
    Leetcode第一题:两数之和 (java & python)
    SpringMVC框架的注解如何使用?
    Mybatis框架的代码自动生成工具如何使用呢?
    Mybatis框架如何使用分页插件呢?
    SpringMVC框架如何实现请求转发和重定向呢?
    文件上传的方式有哪些
    Session的销毁方式到底有哪些?
    找工作就像找对象,愿程序员不再孤单
    java是最值得学习的编程语言吗?
    话说当年学习Java所踩过的坑。。。初学者必看
  • 原文地址:https://www.cnblogs.com/dishu/p/4295403.html
Copyright © 2011-2022 走看看