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;
}

 

posted @ 2016-08-30 09:40  PatrickZhou  阅读(164)  评论(0编辑  收藏  举报