题目:Lighting System Design
题意:
来自luogu——
给定 n(n≤1000)n(n≤1000) 种类型灯泡,每个灯泡给出其电压 v(v≤132000)v(v≤132000) ,电源花费 k(k≤1000)k(k≤1000) ,每个灯的花费 c(c≤10)c(c≤10) 和需求量 l(1≤l≤100)l(1≤l≤100) 。现在通过用电压大的灯泡替换某些电压小的灯泡来减小总花费,求最小的花费。
思路:
先以电压为关键字从小到大排序,此后,只能将排在前面的灯泡换成后面的灯泡。
令f[i]表示只前i种灯泡时的最小化费。
枚举j,令j+1~i的灯泡都变成i,转移方程 f[i]=min{ f[j]+(sum[i]-sum[j])*a[i].c+a[i].k } ,其中sum为前缀和。
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000
#define inf (1<<30)
struct lgt{
int v,k,c,l;
bool operator < (lgt const oth) const {
return v<oth.v;
}
};
int n;
lgt a[maxn+5];
int sum[maxn+5];
int f[maxn+5];
void readin(){
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+n+1);
}
void init(){
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+a[i].l;
f[i]=inf;
}
}
int slv(){
for(int i=1;i<=n;i++){
for(int j=0;j<i;j++){
f[i]=min(f[i],f[j]+(sum[i]-sum[j])*a[i].c+a[i].k);
}
}
return f[n];
}
int main(){
while(~scanf("%d",&n)&&n){
readin();
init();
int ans=slv();
printf("%d\n",ans);
}
return 0;
}