• UVA


      这个问题有两个点需要注意: 1、 对于一种灯泡,要么全换,要么全不换。 证明: 设一种灯泡单价为p1,电池价格为k1,共需要L个,若把L1个灯泡换成单价为p2,电池为k2的灯泡,产生的总花费为p1*L1+k1 + p2*(L-L1)+k2 (1)。全不换为p1*L+k1 (2),全换为p2*L+k2 (3)。让(1)式分别跟(2),(3)式做差,会发现一正一负的情况,从数学的角度上证明了,要么全换,要么全不换。

      2、如果我要用第i种灯泡去替换前面的灯泡,那么一定是连续的替换不可能出现间断,这也是这个问题的核心所在,他的原因很简单,给出一个排列,1,2,3,4,5。5向前替换,不可以出现4没有被替换,而3却被5替换的现象,因为这一定不是最优方案,4不被替换一定是比5更好,那么3就应该被4替换,而不该被5替换,这样对于4又是连续的替换了。 所以区间替换是正确的,也是这里最巧妙的,这样正确的限制决策成功方便了状态转移,并且不会丢失解。

      所以我们定义dp[i]表示处理到第i中灯泡的最小花费,对于第i个灯泡,则是dp[i] = min(dp[i],dp[j] + (s[i]-s[j])*pi + ki),枚举j即连续的替换个数。最后dp[n]即使答案。

      注意:处理的时候需要排序,s[i]用于记录前i个灯泡的和,千万要排序后再记录和,我当时偷懒在输入的时候累加了和,WA了很多次才发现这个错误。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    struct Lamps
    {
        int v,vs,pri,num;
    } l[1100];
    bool cmp(Lamps a,Lamps b)
    {
        return a.v < b.v;
    }
    int dp[1100],suml[1100],n;
    int main()
    {
        while(cin>>n)
        {
            if(n==0) break;
            suml[0] = 0;
            for(int i = 1; i <= n; i++)
            {
                cin>>l[i].v>>l[i].vs>>l[i].pri>>l[i].num;
            }
            dp[0] = 0;
            sort(l+1,l+n+1,cmp);
            for(int i = 1; i <= n; i++)
            {
                suml[i] = suml[i-1]+l[i].num;
            }
            for(int i = 1; i <= n; i++)
            {
                dp[i] = suml[i]*l[i].pri + l[i].vs;
                for(int j = i-1; j >= 0; j--)
                {
                    dp[i] = min(dp[i],dp[j]+(suml[i]-suml[j])*l[i].pri+l[i].vs);
                }
            }
            cout<<dp[n]<<endl;
        }
        return 0;
    }
  • 相关阅读:
    Markdown语法帮助文档
    react-native-vector-icons使用方法
    如何创建Pull Request,以开源项目ant design pro为例
    4.环境变量总结篇
    3.Flutter之hello_world
    构建之法 阅读笔记03
    学习进度14
    团队项目-个人博客6.5
    团队项目-个人博客6.4
    构建之法 阅读笔记02
  • 原文地址:https://www.cnblogs.com/jifahu/p/5817107.html
Copyright © 2020-2023  润新知