[UVA 11400] Lighting System Design

题目描述

你将要为一个会议大厅设计一个照明系统。在做了一些调查和计算之后,你发现有一个节能的设计能满足大厅的照明需求。根据这一设计,你需要n种不同功率的电灯。由于电流调节需要,所有的电灯都需要被通过相同的电流,因此,每一种灯都有对应的额定电压。现在,你已经知道了每一种电灯的数量和单位成本。但问题来了,你将要为所有类别的灯泡买同样的电源。事实上,你也可以为每一种灯泡单独买一种电源(我们认为:一个电源可以为无数个额定电压为电源电压的电灯供电)来完成设计。但是公司财务部很快发现他们可以通过删除一些电源并更换高功率的灯泡。你当然不能把灯泡换成低功率的,因为这样就会使大厅的一部分不能得到照明。你更关心的是节约金钱而不是节约能源,因此你要重新设计一个系统(将一些低电压灯泡更换为高电压灯泡),来使价格最便宜。

输入

有多组数据。
每一组数据以一个整数n (1<=n<=1000),表示灯泡的种类。接下来的n行每一行表示一种灯泡的信息,一行包含4个整数:额定电压V (1<=V<=132000),满足所需电压的电源的单价K (1<=K<=1000),灯泡的单价C (1<=C<=10),需要的灯泡数量L (1<=L<=100)。
n=0时,输入数据结束。

输出

对于每一组数据,输出可能的最小花费。

样例数据

样例输入

样例输出

3
100 500 10 20
120 600 8 16
220 400 7 18
0

778



        (1)一种灯泡要么全换,要么不换,否则不具有最优性;

        (2)按V从小到大排序,然后设dp[i]表示前i种灯泡的最优方案是多少,转移时枚举j<i,j之前的dp值不变,j之后的全都换成i灯泡;

        ※会不会漏解,为什么没有枚举替换j之前的不连续的一部分?其实不存在的,因为i之前的灯泡肯定是越往后花费越大,如果前面的花费反而更大的话,大可以转化为后面的灯泡。

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

inline int read(void){
	int x=0,f=1; char ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1;
	for(;ch>='0'&&ch<='9';x=(x<<3)+(x<<1)+ch-'0',ch=getchar());
	return x*f;
} 

const int maxn=1009;
struct LJM{
	int V,K,C,L;
}ljm[maxn];
int dp[maxn],cnt[maxn];

inline bool cmp(const LJM&a,const LJM&b){
	return a.V<b.V;
}

int main(int argc,char const *argv[]){
	int n;
	for(;~scanf("%d",&n)&&n;){
		for(int i=1;i<=n;i++)
			ljm[i].V=read(),ljm[i].K=read(),
			ljm[i].C=read(),ljm[i].L=read();
		sort(ljm+1,ljm+n+1,cmp);
		for(int i=1;i<=n;i++) cnt[i]=cnt[i-1]+ljm[i].L;
		dp[0]=0;
		for(int i=1;i<=n;i++){
			dp[i]=0x3f3f3f;
		for(int j=0;j<=i;j++)
			dp[i]=min(dp[i],dp[j]+(cnt[i]-cnt[j])*ljm[i].C+ljm[i].K);
		}
		printf("%d\n",dp[n]);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值