9-6 UVa 11400
参考 http://www.cnblogs.com/Kiraa/p/5510757.html
http://www.cnblogs.com/zhaopAC/p/5159950.html
根据题目说明中的这句话
reduce the total system cost by eliminating some of the voltage sources and replacing the
lamps of that category with higher rating lamps.
可以判断某种电压的灯泡如果要换就全换,否则就不会eliminate某种电压。
这条题目的难点在于最优解符合一定的模式。
设d[i]为子问题灯泡1...i的最小开销,当前考虑灯泡种类i,d[i-1]已经是最优解。
编号1...(i-1)代表每种灯泡,按照电压从低到高排序,在最优解中,可能某个编号代表的灯泡已经被替换,但数量不变。
设每种灯泡的参数分别存放在V[],K[],C[],L[]这些数组中。
设 1<=j<=(i-1),j这种灯泡可以被替换成i这种灯泡,那么需要满足以下这些条件
1) V[j] < V[i]
2) K[j] + C[j]*L[j] < C[i]*L[j]
如果在编号 (j+1)...(i-1)这些种类的灯泡中有个编号x != j
因为1...(i-1)这些灯泡已经构成的最优解,j没有被x替换,那么需要满足以下这些条件
3) V[j] < V[x]
4) K[j] + C[j]*L[j] >= C[x]*L[j]
根据公式 2) 和 4)可知
C[x] <= C[i]
所以 K[x] + C[x]*L[x] < C[i]*L[x]
所以x这种灯泡也可以被替换成i
替换的模式是,如果某种灯泡可以被替换成i,那这种灯泡右边的灯泡都可以被替换成i
设s[i]为前i种灯泡的总数量,
d[i] = min{d[j] + (s[i]-s[j])*C[i] + K[i]} // 0 <= j <= (i-1)
1...j不替换,费用是d[j],(j+1)到(i-1)被替换成i,费用是(s[i]-s[j])*C[i] + K[i]
j = 0时,d[0] = 0,s[0] = 0,d[i] = s[i] * C[i] + K[i],相当于全部替换成i
#define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstring> #include <algorithm> #include <numeric> using namespace std; struct Lamp { int V; // 1 <= V <= 132000, voltage rating int K; // 1 <= K <= 1000, cost of voltage source of this rating int C; // 1 <= C <= 10, cost of a lamp of this rating int L; // 1 <= L <= 100, number of lamps required }; int n; // 1 <= n <= 1000 const int maxn = 1000; Lamp a[maxn + 5]; int s[maxn + 5]; int d[maxn + 5]; bool comp(const Lamp &a, const Lamp &b) { return a.V < b.V; } int main() { while (scanf("%d", &n) && n) { 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, comp); // sort based on voltage s[0] = 0; // s[i] = sum of numbers of 1..i types of lamps for (int i = 1; i <= n; i++) { s[i] = s[i - 1] + a[i].L; } d[0] = 0; // d[i] = minium cost with 1..i types of lamps for (int i = 1; i <= n; i++){ d[i] = a[i].K + a[i].C * s[i]; // replace all lamps with type i for (int j = 1; j < i; j++) { d[i] = min(d[i], d[j] + (s[i] - s[j])*a[i].C + a[i].K); // replace j+1...i with type i } } printf("%d\n", d[n]); } return 0; }