一个关键之处在于状态转移的理解。
考虑已经按照电压升序排好序的bulb,假若有a, b, c, d, e那么若是有一些灯泡升级为了e,那么这些灯泡序号必定是连续的,例如b, c灯泡升级为e,但是d 没有,这种“跳跃”的状况是不可能的。缘由以下:
假设这种状况可能,那么上面这个例子中,隔在中间一定有一个没有升级的,在这里是d,显然d不肯意升级为e的缘由只能是d的单价比e要贵(否则的话,所有转化为e,还能省掉电源钱,这样更划算),那那些升级为e的b, c还不如升级成d, 这样成本反而更低,因此可见,这种状态转移必定不是产生最优解的状态转移。ios
#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; }