P1417 烹调方案

原题链接
此题是01背包的变形,与传统01背包不同的是每件物品贡献的计算方式

如果在 \(t\) 时刻完成第 \(i\) 样食材则得到 \(a_i - t × b_i\) 的美味指数

这句话意味着食材的美味指数在不同的时间有着不一样的数值,也就是说,烹调的先后顺序会影响得到的美味指数
假设有两样食材 \(i,j\)
\(a_i = 1,b_i = 0,c_i = 1\)
\(a_j = 1,b_j = 1,c_j = 1\)
假设从 \(0\) 时刻开始烹调:
先烹调 \(i\) 再烹调 \(j\) 得到的美味指数:

$a_j-(c_i+c_j)×b_j+a_i-c_i×b_i=0$
先烹调 $j$ 再烹调 $i$ 得到的美味指数:
$a_i-(c_j+c_i)×b_i+a_j-c_j×b_j=1$
我们希望食材烹调的顺序能保证我们找到最优解,即先烹调位于数组前面的食材所得到的美味指数必定大于先烹调位于数组后面的食材所得到的美味指数,假设 $i$ 在 $j$ 前面,那么就要保证:
$a_j-(c_i+c_j)×b_j+a_i-c_i×b_i>a_i-(c_j+c_i)×b_i+a_j-c_j×b_j$
$c_j×b_i>c_i×b_j$
所以我们可以将食材按照上式进行排序,这样就可以保证整体的最优解了

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100005;
struct node{
	ll a,b,c;
}s[55];
bool cmp(node n1,node n2){
	return n2.c * n1.b > n1.c * n2.b;
}
ll dp[N];
int main(){
	ll t,n,ans = 0;
	cin>>t>>n;
	for(int i=1;i<=n;i++) cin>>s[i].a;
	for(int i=1;i<=n;i++) cin>>s[i].b;
	for(int i=1;i<=n;i++) cin>>s[i].c;
	sort(s + 1,s + n + 1,cmp);
	for(int i=1;i<=n;i++){
		for(int j=t;j>=s[i].c;j--){
			dp[j] = max(dp[j],dp[j - s[i].c] + s[i].a - j * s[i].b);
			ans = max(ans,dp[j]);
		}
	}
	cout<<ans;
	return 0;
}
posted @ 2023-09-03 17:54  yutar  阅读(3)  评论(0)    收藏  举报