『动态规划·贪心』最优价值

这是一道关于动态规划和贪心策略的题目,讨论如何在物品价值因选择顺序而变化的情况下,求解最大价值。文章解释了如何理解价值下降的概念,并提出减去相应权重的策略。状态转移方程为f[i][j]=max(f[i−1][j],f[i−1][j−1]−(j−1)∗wi+vi),其中f[i][j]表示选到第i个物品,选了j件的最大价值。解决方案包括对物品按权重降序排列,然后从小到大选择,以实现最大价值。" 124865865,14072783,Zabbix Web监控详解:监测HTTP状态与页面内容,"['Zabbix', 'Linux', '运维', '前端监控']

题目描述

在这里插入图片描述

题解

这道题可能就是比较经典的费用提前的题吧,但是我考场上莫有想到可能是忘记了吧。

对于费用计算,我们可以这么理解:对于每一件物品,当它使用过以后其他物品的价值都会下降。因此我们在当前状态的时候就减去一个下降的值,这样其他的每一件物品在通过这个状态转移的时候就会下降了。

理解了这么一个思想,我们就有一个问题,就是减去的值为多少呢?我们发现,若这个物品被选的顺序是倒数第一,那么就不选;如果是倒数第二,那就减去一倍的www;倒数第三时,有两个数要减去www,所以在当前状态转移222倍的www。一次类推,如果是倒数第nnn,就减去(n−1)(n-1)(n1)倍的www即可。

除此之外,因为选的顺序是没有要求的,更小的先选会减的更小,所以我们从小到大选取。由于在状态转移的时候需要倒序枚举,所以我们从大到小排序即可。

我们设f[i][j]f[i][j]f[i][j]表示选到第iii个物品,选了jjj件的最大价值。有状态转移方程:f[i][j]=max(f[i−1][j],f[i−1][j−1]−(j−1)∗wi+vi)f[i][j]=max(f[i-1][j],f[i-1][j-1]-(j-1)*w_i+v_i)f[i][j]=max(f[i1][j],f[i1][j1](j1)wi+vi)

代码如下:

#include <bits/stdc++.h>

using namespace std;

int n;
struct node
{
	int v,w;
};
int ans = -1e9;
int f[6000][6000];
node a[1000000];

inline bool cmp(node p1,node p2)
{
	return p1.w>p2.w;
}

int main(void)
{
	freopen("value.in","r",stdin);
	freopen("value.out","w",stdout);
	cin>>n;
	for (int i=1;i<=n;++i) 
		scanf("%d %d",&a[i].v,&a[i].w);
	sort(a+1,a+n+1,cmp);
	for (int i=1;i<=n;++i)
		for (int j=1;j<=i;++j)
	        f[i][j] = max(f[i-1][j], f[i-1][j-1]+a[i].v-(j-1)*a[i].w); 
	for (int i=1;i<=n;++i) ans = max(ans,f[n][i]);
	cout<<ans<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值