UVa 11400

一個關鍵之處在於狀態轉移的理解。
考慮已經按照電壓升序排好序的bulb,假若有a, b, c, d, e那麼若是有一些燈泡升級爲了e,那麼這些燈泡序號必定是連續的,例如b, c燈泡升級爲e,但是d 沒有,這種「跳躍」的狀況是不可能的。緣由以下:
假設這種狀況可能,那麼上面這個例子中,隔在中間一定有一個沒有升級的,在這裏是d,顯然d不肯意升級爲e的緣由只能是d的單價比e要貴(否則的話,所有轉化爲e,還能省掉電源錢,這樣更划算),那那些升級爲e的b, c還不如升級成d, 這樣成本反而更低,因此可見,這種狀態轉移必定不是產生最優解的狀態轉移。ios

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <cmath>
#include <vector>
using namespace std;

const int maxn= 1005;
const int INF= 0x3f3f3f3f;

struct bulb
{
	int v, k, c, l;
	bulb()=default;
	bulb(int vv, int kk, int cc, int ll) : v(vv), k(kk), c(cc), l(ll) {} 
	bool operator < (const bulb & b) const 
	{
		return this->v < b.v;
	}
}ls[maxn];
int s[maxn], dp[maxn];

void Init(int n)
{
	s[0]= 0;

	memset(dp, 0x3f, sizeof(dp));
	dp[0]= 0;

	for (int i= 1; i<= n; ++i){
		s[i]= s[i-1]+ls[i].l;
	}
}

int main()
{
	int n;
	int v, k, c, l;

	while (1== scanf("%d", &n) && n){
		for (int i= 1; i<= n; ++i){
			scanf("%d %d %d %d", &v, &k, &c, &l);
			ls[i]= bulb(v, k, c, l);
		}
		sort(ls+1, ls+n+1);
		Init(n);

		for (int i= 1; i<= n; ++i){
			int &x= dp[i];
			c= ls[i].c;

			for (int j= i-1; j>= 0; --j){
				x= min(x, dp[j]+(s[i]-s[j])*c);
			}
			x+= ls[i].k;
		}
		printf("%d\n", dp[n]);
	}

	return 0;
}
相關文章
相關標籤/搜索