1. 程式人生 > 其它 >UVa 11400 - Lighting System Design (dp)

UVa 11400 - Lighting System Design (dp)

題目連結:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2395

要換燈泡的話,一定是這個種類的全換,將燈泡按電壓排序,如果有燈的種類要替換成燈 \(i\),那麼燈 \(i\)\(c[i]*l[i]+k[i]\) 一定是這段區間中最小的,最終替換成的所有燈泡的 \(c[i]*l[i]+k[i]\) 一定是遞增的,如下圖

紅線是燈泡原來的值,黑框是替換以後的值的樣子

所以我們就可以考慮 \(dp\),令 \(dp[i]\) 表示前 \(i\)

個燈泡的答案,轉移是考慮從哪一段開始將這些燈泡都替換成燈泡 \(i\)

\[dp[i] = max{dp[j]+(s[j]-s[i])*c[i]+k[i]}(0<=j<i) \]

其中 \(s[i]\) 表示前 \(i\) 個燈泡的總數量

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 1010;

int n;
int s[maxn], dp[maxn];

struct Lamp{
	int v, k, c, l;
	
	bool operator < (const Lamp &x) const{
		return v < x.v;
	}
}a[maxn];

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }

int main(){
	while(scanf("%d", &n) == 1 && 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 + 1 + n);
		
		s[0] = 0;
		for(int i = 1 ; i <= n ; ++i) s[i] = s[i-1] + a[i].l; 
		
		memset(dp, 0x3f, sizeof(dp));
		dp[0] = 0;
		
		for(int i = 1 ; i <= n ; ++i){
			for(int j = 0 ; j < i ; ++j){
				dp[i] = min(dp[i], dp[j] + (s[i] - s[j]) * a[i].c + a[i].k);
			}
		}
		printf("%d\n", dp[n]);
	} 
	return 0;
}