Lighting System Design
你的任务是设计一个照明系统。一共有n种灯泡可供选择,不同种类的灯泡必须用不同的电源,但一种灯泡可以共用一个电源。每种灯泡用4给数值表示:电压V,电源费用K,灯泡单价C和所需灯泡的数目L。
假设通过所有的灯泡的电流都相同,因此电压高的灯泡功率也大。为了省钱,可以把一些灯泡换成电压更高的另一种灯泡以节省电源的钱(但不能换成电压更低的灯泡)。求最优方案的费用。
题目很难懂。举个例子的话
假如有三种灯泡(已经按电压升序排列)
编号 | 电压 | 电源费用 | 单价 | 数量 |
---|---|---|---|---|
1 | 100 | 500 | 10 | 20 |
2 | 120 | 600 | 8 | 16 |
3 | 220 | 400 | 7 | 18 |
题目中最初的时候,我们是要把所有的灯泡都安上的,所以费用的计算过程是
1、500+10x20
2、600+8x6+前面之和
3、400+7x18+前面之和
这是每种电源都选上了,但是我们可以用高电压的灯泡替换低电压的,例如
我们之选用120v的电源,也就是说我们把100v的灯泡全部都换成了120v的,但是数量不变,那么到第二个的时候,我们的总费用就变成了600+8*(20+16) ,由于有时候电源比较便宜,所以即使我们增加了购买的数量,我们的价格反而会降低。
由于只能用高电压换低电压,所以我们在计算前先把电压从小到大排序。用前缀和记录需要更换的数量,记得在之排序后再求前缀和。
当然,我们也可以不选择全部的灯泡来替换,而选择部分电压的。
由此我们可以列出状态转移方程:
(dp[i]表示选到第i种灯泡时的最优价格)
d
p
[
i
]
=
m
i
n
(
d
p
[
j
]
+
C
i
∗
∑
k
=
j
i
n
u
m
k
)
j
∈
[
1
,
i
]
dp[i]=min(dp[j]+C_i*\sum_{k=j}^{i}{num_k}) \quad j∈[1,i]
dp[i]=min(dp[j]+Ci∗k=j∑inumk)j∈[1,i]
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
#define ull unsigned long long
#define mem(a,b) memset(a,b,sizeof(a));
using namespace std;
const int maxn = 1010;
const int inf = 0x3f3f3f3f;
struct node
{
int v, k, c, l;
bool operator<(node &b)
{
return v < b.v;
}
}a[maxn];
int s[maxn];
int dp[maxn];//选择到第i号电源时的最小化花费
int main()
{
int n;
while (scanf("%d", &n) && n != 0)
{
for (int 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);
mem(dp, inf);
dp[0] = 0, s[0] = 0;
for (int i = 1; i <= n; i++)
{
s[i] = s[i - 1] + a[i].l;
for (int j = 1; j <= i; j++)//把第j种到第i种的灯泡全用i号电源
{
int num = s[i] - s[j - 1];
dp[i] = min(dp[i], dp[j - 1] + num * a[i].c + a[i].k);
}
}
printf("%d\n", dp[n]);
}
return 0;
}