南沙C++信奧賽陳老師解一本通題 1984:【19CSPJ普及組】紀念品

南沙区信奥赛陈老师發表於2024-10-02

【題目描述】

小偉突然獲得一種超能力,他知道未來 T 天 NN種紀念品每天的價格。某個紀念品的價格是指購買一個該紀念品所需的金幣數量,以及賣出一個該紀念品換回的金幣數量。

每天,小偉可以進行以下兩種交易無限次:

1.任選一個紀念品,若手上有足夠金幣,以當日價格購買該紀念品;

2.賣出持有的任意一個紀念品,以當日價格換回金幣。

每天賣出紀念品換回的金幣可以立即用於購買紀念品,當日購買的紀念品也可以當日賣出換回金幣。當然,一直持有紀念品也是可以的。

TT 天之後,小偉的超能力消失。因此他一定會在第 TT 天賣出所有紀念品換回金幣。

小偉現在有 MM 枚金幣,他想要在超能力消失後擁有儘可能多的金幣。

【輸入】

第一行包含三個正整數 T, N, M,相鄰兩數之間以一個空格分開,分別代表未來天數T,紀念品數量 NN,小偉現在擁有的金幣數量 M。

接下來 TT 行,每行包含 N 個正整數,相鄰兩數之間以一個空格分隔。第 i行的N 個正整數分別為 Pi,1,Pi,2,……,Pi,N,其中 Pi,j表示第 i天第 j種紀念品的價格。

【輸出】

輸出僅一行,包含一個正整數,表示小偉在超能力消失後最多能擁有的金幣數量。

【輸入樣例】

6 1 100
50
20
25
20
25
50

【輸出樣例】

305

【提示】

【輸入輸出樣例 1 說明】

最佳策略是:

第二天花光所有 100 枚金幣買入 5 個紀念品 1;

第三天賣出 5 個紀念品 1,獲得金幣 125 枚;

第四天買入 6 個紀念品 1,剩餘 5 枚金幣;

第六天必須賣出所有紀念品換回 300 枚金幣,第四天剩餘 5 枚金幣,共 305 枚金幣。

超能力消失後,小偉最多擁有 305 枚金幣。

【輸入輸出樣例 2】

3 3 100
10 20 15
15 17 13
15 25 16

【輸入輸出樣例 2】

217

【輸入輸出樣例 2 說明】

最佳策略是:

第一天花光所有金幣買入 10 個紀念品 1;

第二天賣出全部紀念品 1 得到 150 枚金幣並買入 8 個紀念品 2 和 1 個紀念品 3,剩餘 1 枚金幣;

第三天必須賣出所有紀念品換回 216 枚金幣,第二天剩餘 1 枚金幣,共 217 枚金幣。

超能力消失後,小偉最多擁有 217 枚金幣。

【資料規模與約定】

對於 10% 的資料,T=1T=1。

對於 30% 的資料,T≤4,N≤4,M≤100,所有價格 10≤Pi,j≤100。

另有 15% 的資料,T≤100,N=1。

另有 15% 的資料,T=2,N≤100。

對於 100% 的資料,T≤100,N≤100,M≤103,所有價格 1≤Pi,j≤104,資料保證任意時刻,小明手上的金幣數不可能超過104

#include <bits/stdc++.h>
using namespace std;
int dp[201][10005];  //i為行件物品放到容易為j為列的揹包產生的最大價值 
int w[201],v[201],a[201][201]; //分別為重量 價值 
int Pack(int n,int m)	//完全揹包  注意揹包容易m每天是遞增的 
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(w[i]>j)
				dp[i][j]=dp[i-1][j];
			else
			{
				int put=v[i]+dp[i][j-w[i]];
				int noput=dp[i-1][j];
				dp[i][j]=max(put,noput);
			}
		}
	}
	return dp[n][m];
}
int main()
{
	int t, n, m;
	cin>>t>>n>>m;
	for(int i=1;i<=t;i++)
		for(int j=1;j<=n;j++)
			cin>>a[i][j];
	for(int i=1;i<t;i++)
	{
		memset(w,0,sizeof(w));
		memset(v,0,sizeof(v));
		memset(dp,0,sizeof(dp));
		for(int j=1;j<=n;j++)
		{
			w[j]=a[i][j];
			v[j]=a[i+1][j]-a[i][j];
		}
		m += Pack(n,m);////每天后揹包容量增值了 
	}
	cout << m; 
	return 0;
}
南沙C++信奧賽陳老師解一本通題 1984:【19CSPJ普及組】紀念品

相關文章