poj1260 Pearls (dp)

又是一道依靠别人的题解才做出来的dp,为什么要说“又”呢...233

题意:给出几类珍珠,以及它们的单价,规定买任一类的珍珠n个(价格为p),都要支付(n+10)*p的钱,即额外支付10*p(什么鬼设定),低档的珍珠可以按高档珍珠的价钱买,反之不行,由于低档的按高档的买了,可以少支付低档的那10*p的钱,因此可能会比正常买便宜,现在要求算出买所有珍珠的最低价。

分析:思路类似脑经急转弯,只要注意到这一点就行了:若a、b、c三种珍珠,档次递增 ,若a被b替代能便宜,b被c替代也能便宜,则a被c替代一定能便宜。因此这种替代是连续的,要找的就是一个个不重叠的替代区间,区间内的所有珍珠都被最后一类珍珠替代。

由此可得状态转移方程:

dp[i] = (a[i] + 10)*p[i] + dp[i - 1];   初始化,未进行优化前的价格

dp[i] = min(dp[i], (sum[i] - sum[j] + 10)*p[i] + dp[j]);     0<=j<i, 枚举j进行价格优化

代码如下:

#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstring>
using namespace std;

int a[105], sum[105], p[105];
int dp[105];
int main()
{
	//fstream cin("test.txt");
	int k;
	cin >> k;
	while (k--)
	{
		memset(sum, 0, sizeof(sum));
		int n;
		cin >> n;
		for (int i = 1; i <= n; i++)
		{
			cin >> a[i] >> p[i];
			sum[i] = sum[i - 1] + a[i];
		}
		dp[0] = 0;
		for (int i = 1; i <= n; i++)
		{
			dp[i] = (a[i] + 10)*p[i] + dp[i - 1];
			for (int j = 0; j < i; j++)
				dp[i] = min(dp[i], (sum[i] - sum[j] + 10)*p[i] + dp[j]);
		}
		cout << dp[n] << endl;
	}
	//system("pause");
	return 0;
}

这种dp说难不难,但自己独立做就是做不出..愁啊

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值