UVa 11400
一个关键之处在于状态转移的理解。
考虑已经按照电压升序排好序的bulb,假如有a, b, c, d, e那么如果有一些灯泡升级为了e,那么这些灯泡序号一定是连续的,例如b, c灯泡升级为e,可是d 没有,这种“跳跃”的情况是不可能的。原因如下:
假设这种情况可能,那么上面这个例子中,隔在中间必定有一个没有升级的,在这里是d,显然d不愿意升级为e的原因只能是d的单价比e要贵(不然的话,全部转化为e,还能省掉电源钱,这样更划算),那那些升级为e的b, c还不如升级成d, 这样成本反而更低,所以可见,这种状态转移一定不是产生最优解的状态转移。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <cmath>
#include <vector>
using namespace std;
const int maxn= 1005;
const int INF= 0x3f3f3f3f;
struct bulb
{
int v, k, c, l;
bulb()=default;
bulb(int vv, int kk, int cc, int ll) : v(vv), k(kk), c(cc), l(ll) {}
bool operator < (const bulb & b) const
{
return this->v < b.v;
}
}ls[maxn];
int s[maxn], dp[maxn];
void Init(int n)
{
s[0]= 0;
memset(dp, 0x3f, sizeof(dp));
dp[0]= 0;
for (int i= 1; i<= n; ++i){
s[i]= s[i-1]+ls[i].l;
}
}
int main()
{
int n;
int v, k, c, l;
while (1== scanf("%d", &n) && n){
for (int i= 1; i<= n; ++i){
scanf("%d %d %d %d", &v, &k, &c, &l);
ls[i]= bulb(v, k, c, l);
}
sort(ls+1, ls+n+1);
Init(n);
for (int i= 1; i<= n; ++i){
int &x= dp[i];
c= ls[i].c;
for (int j= i-1; j>= 0; --j){
x= min(x, dp[j]+(s[i]-s[j])*c);
}
x+= ls[i].k;
}
printf("%d\n", dp[n]);
}
return 0;
}