题目大意:有一个照明系统需要用到n种灯,每种灯的电压为V,电源费用K,每个灯泡费用为C,需要该灯的数量为L。注意到,电压相同的灯泡只需要共享一个对应的电源即可,还有电压低的灯泡可以被电压高的灯泡替代。为了节约成本,你将设计一种系统,使之最便宜。
分析:首先需要明确一种灯泡要么全部换,要么不换。如果换一部分的话,首先电源费用得不到节约,那么节约的部分就只来自于换的那部分灯泡,既然可以节约钱干嘛不干脆全部换了呢?所以要么全换,要么不换。然后我们的算法就是先按照V排序,然后cost[i]表示解决前 i 种灯泡的最优解,那么转移方程是枚举j<i,将j之前的保持最优解cost[j]不变,j之后的全部变成i种灯泡。有一个疑问是:是不是会漏解,为什么没有枚举替换j之前的不连续的一部分?这个问题其实不存在,因为i之前的灯泡肯定是越后面的花费越大,因为如果前面的花费反而更大的话,大可以转换为后面的灯泡。
首先需要明确一种灯泡要么全部换,要么不换。如果换一部分的话,首先电源费用得不到节约,那么节约的部分就只来自于换的那部分灯泡,既然可以节约钱干嘛不干脆全部换了呢?所以要么全换,要么不换。然后我们的算法就是先按照V排序,然后cost[i]表示解决前
i 种灯泡的最优解,那么转移方程是枚举j<i,将j之前的保持最优解cost[j]不变,j之后的全部变成i种灯泡。有一个疑问是:是不是会漏解,为什么没有枚举替换j之前的不连续的一部分?这个问题其实不存在,因为i之前的灯泡肯定是越后面的花费越大,因为如果前面的花费反而更大的话,大可以转换为后面的灯泡。
如果我要用第i种灯泡去替换前面的灯泡,那么一定是连续的替换,不可能出现间断,这也是这个问题的核心所在,他的原因很简单,给出一个排列,1,2,3,4,5。5向前替换,不可以出现4没有被替换,而3却被5替换的现象,因为这一定不是最优方案,4不被替换一定是比5更好,那么3就应该被4替换,而不该被5替换,这样对于4又是连续的替换了。
分析:首先需要明确一种灯泡要么全部换,要么不换。如果换一部分的话,首先电源费用得不到节约,那么节约的部分就只来自于换的那部分灯泡,既然可以节约钱干嘛不干脆全部换了呢?所以要么全换,要么不换。然后我们的算法就是先按照V排序,然后cost[i]表示解决前 i 种灯泡的最优解,那么转移方程是枚举j<i,将j之前的保持最优解cost[j]不变,j之后的全部变成i种灯泡。有一个疑问是:是不是会漏解,为什么没有枚举替换j之前的不连续的一部分?这个问题其实不存在,因为i之前的灯泡肯定是越后面的花费越大,因为如果前面的花费反而更大的话,大可以转换为后面的灯泡。
首先需要明确一种灯泡要么全部换,要么不换。如果换一部分的话,首先电源费用得不到节约,那么节约的部分就只来自于换的那部分灯泡,既然可以节约钱干嘛不干脆全部换了呢?所以要么全换,要么不换。然后我们的算法就是先按照V排序,然后cost[i]表示解决前
i 种灯泡的最优解,那么转移方程是枚举j<i,将j之前的保持最优解cost[j]不变,j之后的全部变成i种灯泡。有一个疑问是:是不是会漏解,为什么没有枚举替换j之前的不连续的一部分?这个问题其实不存在,因为i之前的灯泡肯定是越后面的花费越大,因为如果前面的花费反而更大的话,大可以转换为后面的灯泡。
如果我要用第i种灯泡去替换前面的灯泡,那么一定是连续的替换,不可能出现间断,这也是这个问题的核心所在,他的原因很简单,给出一个排列,1,2,3,4,5。5向前替换,不可以出现4没有被替换,而3却被5替换的现象,因为这一定不是最优方案,4不被替换一定是比5更好,那么3就应该被4替换,而不该被5替换,这样对于4又是连续的替换了。
所以区间替换是正确的,也是这里最巧妙的,这样正确的限制决策成功方便了状态转移,并且不会丢失解。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct E{
int v,k,c,l;
bool operator < (const E& x)const{
return v<x.v;
}
}a[1050];
int sum[1050],dp[1050];
int main()
{
int n,i,j;
while(scanf("%d",&n)&&n){
for(i=1;i<=n;i++){
scanf("%d%d%d%d",&a[i].v,&a[i].k,&a[i].c,&a[i].l);
}
sort(a+1,a+1+n);
for(i=1;i<=n;i++){
sum[i]=sum[i-1]+a[i].l;
}
for(i=1;i<=n;i++){
dp[i]=sum[i]*a[i].c+a[i].k;
for(j=0;j<i;j++){
dp[i]=min(dp[i],dp[j]+(sum[i]-sum[j])*a[i].c+a[i].k);
}
}
printf("%d\n",dp[n]);
}
return 0;
}