Problem Description
You are given the task to design a lighting system for a huge conference hall. After doing a lot of calculation and sketching, you have figured out the requirements for an energy-efficient design that can properly illuminate the entire hall. According to your design, you need lamps of n different power ratings. For some strange current regulation method, all the lamps need to be fed with the same amount of current. So, each category of lamp has a corresponding voltage rating. Now, you know the number of lamps and cost of every single unit of lamp for each category. But the problem is, you are to buy equivalent voltage sources for all the lamp categories. You can buy a single voltage source for each category (Each source is capable of supplying to infinite number of lamps of its voltage rating.) and complete the design. But the accounts section of your company soon figures out that they might be able to reduce the total system cost by eliminating some of the voltage sources and replacing the lamps of that category with higher rating lamps. Certainly you can never replace a lamp by a lower rating lamp as some portion of the hall might not be illuminated then. You are more concerned about money-saving than energy-saving. Find the minimum possible cost to design the system.
Input
Each case in the input begins with n (1 ≤ n ≤ 1000), denoting the number of categories. Each of the following n lines describes a category. A category is described by 4 integers - V (1 ≤ V ≤ 132000), the voltage rating, K (1 ≤ K ≤ 1000), the cost of a voltage source of this rating, C (1 ≤ C ≤ 10), the cost of a lamp of this rating and L (1 ≤ L ≤ 100), the number of lamps required in this category. The input terminates with a test case where n = 0. This case should not be processed.
Output
For each test case, print the minimum possible cost to design the system.
Sample Input
3
100 500 10 20
120 600 8 16
220 400 7 18
0
Sample Output
778
My Problem Report
这道题代码非常简单,状态也不复杂,但值得好好总结一番。
我在看题解之前自己建立了一个二维的状态,最后发现时间复杂度太高了。这道题的突破口在于总结出一个规律“每种电压的灯泡要么全换,要么全不换”。
为什么这个规律这么重要呢?因为它将一个多重背包问题转化成了一个0/1背包问题,我们的状态也就随之简化了很多。其实一开始我在发现自己建立的状态效率太低的时候就应该思考一下下面两种可能:
1.状态建复杂了,或者有技巧可以将状态简化
2.状态建错误了,或者是把题意理解得太复杂。
此题具体的状态和状态转移在《入门经典》上已写得非常详细,这里不再累述。
My Source Code
// Created by Chlerry in 2015.
// Copyright (c) 2015 Chlerry. All rights reserved.
//
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <cstring>
#include <climits>
#include <string>
#include <vector>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define Size 1010
#define ll long long
#define mk make_pair
#define pb push_back
#define mem(array, x) memset(array,x,sizeof(array))
typedef pair<int,int> P;
struct point
{
int v,k,c,l;
}a[Size];
int n,cnt[Size],f[Size];
bool cmp(point a,point b)
{
return a.v<b.v;
}
int main()
{
// freopen("in.txt","r",stdin);
while(cin>>n && n)
{
for(int i=1;i<=n;i++)
cin>>a[i].v>>a[i].k>>a[i].c>>a[i].l;
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
cnt[i]=cnt[i-1]+a[i].l;
for(int i=1;i<=n;i++)
{
f[i]=INT_MAX;
for(int j=0;j<i;j++)
f[i]=min(f[i],f[j]+(cnt[i]-cnt[j])*a[i].c+a[i].k);
}
cout<<f[n]<<endl;
}
return 0;
}