UVa 11400 - Lighting System Design(线性DP)

链接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2395

 

题意:

有n(n≤1000)种灯泡,不同种类的灯泡必须用不同的电源,但同一种灯泡可以共用一个电源。
每种灯泡用4个数值表示:电压值V(V≤132000),电源费用K(K≤1000),灯泡单价C(C≤10)和所需数量L(1≤L≤100)。
可以把一些灯泡换成电压更高的另一种灯泡以节省电源的钱(但不能换成电压更低的灯泡)。求最优方案的费用。

 

分析:

首先可以得到一个结论:每种灯泡要么全换,要么全不换。因为如果把1个灯泡A换成灯泡B能省钱的话,干脆全换得了。
先把灯泡按电压值从小到大排序,这样的话前面的灯泡可以换成后面的灯泡,反之不行。
然后依次考虑每一种灯泡,对于第i种灯泡,尝试将前x(0≤x<i)种灯泡用原来的最优方案,后面的灯泡全用第i种。
为什么是后面的(即连续的)呢?有没有不连续的情况呢?比如灯泡A,B,C(按电压值升序),会不会有A换成C,
而B不换成C的情况呢?答案是没有的。因为如果B不换成C,则必然有:电源B + 单价B * 数量B < 单价C * 数量B。
可见A换成B更优,所以不会出现这种情况。
设sum[i]为前i种灯泡的总数量(即L值之和),d[i]为前i种灯泡的最小费用,
则d[i] = min{d[j] + (sum[i]-sum[j])*c[i] + k[i]},0≤j<i(d[0]表示全用第i种)。答案为d[n]。

 

代码:

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 const int UP = 1000 + 5;
 6 struct LAMP {
 7     int V, K, C, L; //电压,电源费,单价,数量
 8     bool operator < (const LAMP& that) const {
 9         return V < that.V;
10     }
11 } a[UP];
12 
13 int sum[UP], d[UP]; //sum[x]表示前x种灯泡的总数量,d[x]表示前x种灯泡的最小费用
14 
15 int main(){
16     int n;
17     while(scanf("%d", &n) && n){
18         for(int i = 0; i < n; i++)
19             scanf("%d%d%d%d", &a[i].V, &a[i].K, &a[i].C, &a[i].L);
20         sort(a, a + n);
21 
22         sum[0] = a[0].L;
23         for(int i = 1; i < n; i++) sum[i] = sum[i-1] + a[i].L;
24         for(int i = 0; i < n; i++){
25             d[i] = sum[i] * a[i].C + a[i].K; //前sum[i]个灯泡都用类型i
26             for(int t = 0; t < i; t++)
27                 d[i] = min(d[i], d[t] + (sum[i] - sum[t]) * a[i].C + a[i].K);
28         }
29         printf("%d\n", d[n-1]);
30     }
31     return 0;
32 }

 

posted @ 2018-03-15 14:46  Ctfes  阅读(254)  评论(0编辑  收藏  举报