题目
思路
1.首先有结论,每种电压的灯泡,要么全换要么不换,一种电压灯泡部分换部分不换易证是不划算的。
2.状态定义:d(i),灯泡1~i的最小开销。
3.初状态:d[0]=0,d[1]= A[1].K + A[1].L * A[1].C, d[2~n] = INF。
4.答案:d[n]
5.状态转移方程:
- 其中,j < i,s[i]表示前i种灯泡的总数目,也就是前缀和。
- 表示的就是前j种先用最优方案买,然后第j+1~i种都用第i号电池。
代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
#define _rep(i,a,b) for(int i = (a); i<=(b); i++)
using namespace std;
const int INF = 1<<30;
const int maxn = 1000+10;
int n, d[maxn], s[maxn];
struct light{
int V,K,C,L;
bool operator < (const struct light &rhs) const {
return V<rhs.V;
}
}A[maxn];
int main(){
while(scanf("%d",&n) == 1 && n){
_rep(i,1,n) scanf("%d%d%d%d",&A[i].V,&A[i].K,&A[i].C,&A[i].L);
sort(A+1,A+1+n);
memset(s,0,sizeof(s));
_rep(i, 1, n) s[i] = s[i-1] + A[i].L;
_rep(i,1,n) d[i] = INF;
d[0] = 0;
d[1] = A[1].K + A[1].L * A[1].C;
_rep(i,2,n)
_rep(j,0,i-1)
d[i] = min(d[i], d[j]+(s[i] - s[j]) * A[i].C + A[i].K);
printf("%d\n",d[n]);
}
return 0;
}