UVa 11400-
Lighting SystemDesign
题意:要设计一个照明系统,有n种灯泡要使用,每种灯泡有4个参数,电压V,一个电源费用K,一个灯泡的费用C,以及选择该灯泡时需要的数量L,多个同种灯泡可以共用一个电源,不同灯泡需要对应的电源,电压低的灯泡可以用电压高的灯泡代替,求设计这个照明系统的最低花费。
分析:问题求解需要得到2个结论。
1、:一种灯泡,要么全选,要么全不选,证明:设有两种灯泡,一共选择x个,如果第一种选择y个,那么总花费为k1+k2+(C2-C1)*y+C2*x..①,如果只选择第一个,花费为K1+C1*x…②,全选第二个,花费为K2+C2*x…③,①式与后面②③做差可知总有一个大于0,即总存在更小的方案,不论C1与C2,X为何值,多种灯泡同理可证。
2、选择前i种灯泡时,如果要替换,只会替换一个连续区间的灯泡种类,即全部替换j+1到i-1为i这种灯泡。证明:如果J到i当中有一种灯泡x不替换,其他的全部替换为第i种,那么必然是选择x这种灯泡会更优,那么最优方案中j+1到x中这些灯泡应该被替换为x这种,而不应该替换为i这种灯泡,与假设矛盾,所以只会替换一连续区间的灯泡。
有了以上两个结论,便可以设计状态及转移方程了,设dp[i]为选前i种灯泡的最小花费,那么根据决策共有i种状态转移, dp[i] = min(dp[j]+(sum[i]-sum[j])*la[i].c+la[i].k,dp[i]),sum数组为灯泡数量的前缀和,转移方程类似于最长上升子序列问题,难怪紫书上面这个例题放在LIS问题之后.......
做这个题的时候,想了各种dp方程,要么难以转移,要么会漏解,后面无奈去参考了下紫书的分析,才发现没有这么直接….想来也对,很多题都是这样,没有根据题目条件,通过一定的分析,得到某些结论,那么问题便无法求解,突然才知道数学能力的重要性,这是我的一个很大的不足,通过这题也更加说明了知识才是基础!!!
#include
#include
#include
#include
#include
#define LL long long
#define INF 0x3f3f3f3f
#define N 1010
using namespace std;
int sum[N], dp[N];
struct lamp{
int v, k, c, l;
}la[N];
inline int cmp(lamp x, lamp y) {return x.v < y.v;}
int main()
{
int n;
while (scanf("%d", &n), n){
for (int i = 1; i <= n; i++) scanf("%d %d %d %d", &la[i].v, &la[i].k, &la[i].c, &la[i].l);
sort(la+1, la+1+n, cmp);
for (int i = 1; i <= n; i++) sum[i] = sum[i-1]+la[i].l;
for (int i = 1; i <= n; i++){
dp[i] = INF;
for (int j = 0; j < i; j++) dp[i] = min(dp[j]+(sum[i]-sum[j])*la[i].c+la[i].k, dp[i]);
}
printf("%d
", dp[n]);
}
return 0;
}