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說難不難,但自己獨立做就是做不出..愁啊

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章