UVa 11400

一个关键之处在于状态转移的理解。
考虑已经按照电压升序排好序的bulb,假如有a, b, c, d, e那么如果有一些灯泡升级为了e,那么这些灯泡序号一定是连续的,例如b, c灯泡升级为e,可是d 没有,这种“跳跃”的情况是不可能的。原因如下:
假设这种情况可能,那么上面这个例子中,隔在中间必定有一个没有升级的,在这里是d,显然d不愿意升级为e的原因只能是d的单价比e要贵(不然的话,全部转化为e,还能省掉电源钱,这样更划算),那那些升级为e的b, c还不如升级成d, 这样成本反而更低,所以可见,这种状态转移一定不是产生最优解的状态转移。

#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;
}
posted @ 2020-10-07 00:31  IdiotNe  阅读(65)  评论(0编辑  收藏  举报