uva11400--Lighting System Design DP

来源:互联网 发布:淘宝有没有隐形降权 编辑:程序博客网 时间:2024/06/04 14:22

题目链接:

https://cn.vjudge.net/problem/UVA-11400

题目大意:

给出n种灯泡的单价(C)、需求量(L)、电压(V)与电压的价格(K)(同种灯泡可共用一个电源)
低压灯泡可用相等数量的高压灯泡替换
求最小花费

解题思路:

首先,我们可以发现如果要用高亚灯泡替代一种低压灯泡,一定是低压灯泡被全部替代时最优。因为如果换一部分的话,不会减少电源花费,那就只会在灯泡花费上省钱,但既然可以在灯泡上省钱,那不是换得越多省的越多么?而且,全部换完,还可以剩下一个电源的钱。
那么我们就可以定义状态f[i]表示:前i种灯泡的最小花费。
这样如果我们用sum[i]表示灯泡数量的前缀和的话,就不难得出一下状态转移方程式:f[i] = min(f[j]+(sum[i]-sum[j])*C[i]+K[i])
值得注意的是:为什么我们可以只替换连续的一段就得到最后的正确答案呢?这样做不会少了很多情况吗?比如说只替换前面的某种灯泡,或者我间断性的替换灯泡,会不会更优呢?
其实:这种情况是不存在的,因为

  1. 如果我要用当前灯泡i去替换前面的某种灯泡k,只可能是使用k并没有一起使用i优。
  2. 我不用当前i去替换灯泡j∈(k,i),只可能是i并没有j优。

但,如果j比i优,i比k优,那么j就比k优,所以我们就不需要用i去替换k了,因为在那之前j已经替换了k并将最优值保存到了f[j]中。

所以,不连续的替换是不存在的,当i要替换k时,一定会保证i比∀j∈(k,i)都要优,否则就不会替换k

此外,为了保证i一定能替换i前面的灯泡,所以这里我们要先按照电压(V)从小到大排序

Code:

#include <cstdio>#include <algorithm>using namespace std;const int MAXN = 1005;int n, f[MAXN], sum[MAXN];struct Node{    int v, k, c, l;    bool operator < (const Node &x) const{        return v < x.v;    }}p[MAXN];int main(){    while(scanf("%d",&n), n){        for(int i = 1; i <= n; ++ i)            scanf("%d%d%d%d",&p[i].v,&p[i].k,&p[i].c,&p[i].l);        sort(p+1, p+n+1);        for(int i = 1; i <= n; ++ i){            sum[i] = sum[i-1]+p[i].l;            f[i] = sum[i]*p[i].c+p[i].k;            for(int j = 1; j < i; ++ j)                f[i] = min(f[i], f[j]+(sum[i]-sum[j])*p[i].c+p[i].k);        }        printf("%d\n",f[n]);    }    return 0;}
原创粉丝点击