【USACO10JAN】Cheese Towers S 奶酪塔 (背包dp)

4 篇文章 0 订阅

一种思路奇特的做法。

看到题目容易联想到背包dp,因为看上去很像

但是我们并不知道上面有没有大奶酪。

所以我们不妨倒过来看,从上往下加奶酪。

d p ( i , 1 / 0 ) dp(i,1/0) dp(i,1/0) 表示当前从上往下的累加高度为 i i i,这之中有/无大奶酪。

显然,当我们考虑新加一个奶酪时,有:

{ d p ( i , 0 ) = max ⁡ ( d p ( i − h j , 0 ) + v j )    ( h j < K ) d p ( i , 1 ) = max ⁡ ( d p ( i − h j , 0 ) + v j )    ( h j ≥ K ) \begin{cases} dp(i,0)=\max(dp(i-h_j,0)+v_j)\ \ (h_j<K)\\ dp(i,1)=\max(dp(i-h_j,0)+v_j)\ \ (h_j\geq K) \end{cases} {dp(i,0)=max(dp(ihj,0)+vj)  (hj<K)dp(i,1)=max(dp(ihj,0)+vj)  (hjK)

然后对于 d p ( i , 1 ) dp(i,1) dp(i,1),还有:

d p ( i , 1 ) = max ⁡ ( d p ( i − 4 5 h j , 1 ) + v j ) dp(i,1)=\max(dp(i-\frac{4}{5}h_j,1)+v_j) dp(i,1)=max(dp(i54hj,1)+vj)

总的时间复杂度 O ( n t ) O(nt) O(nt),听说 O ( n 2 t ) O(n^2t) O(n2t) 也能过……

#include<bits/stdc++.h>

#define N 110
#define T 1010

using namespace std;

int n,t,k,ans;
int v[N],h[N];
int dp[T][2];

int main()
{
	scanf("%d%d%d",&n,&t,&k);
	for(int i=1;i<=n;i++)
		scanf("%d%d",&v[i],&h[i]);
	memset(dp,128,sizeof(dp));
	dp[0][0]=0;
	for(int i=0;i<=t;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(i-h[j]>=0)
			{
				if(h[j]<k) dp[i][0]=max(dp[i][0],dp[i-h[j]][0]+v[j]);
				else dp[i][1]=max(dp[i][1],dp[i-h[j]][0]+v[j]);
			}
		}
		for(int j=1;j<=n;j++)
			if(i-h[j]*4/5>=0)
				dp[i][1]=max(dp[i][1],dp[i-h[j]*4/5][1]+v[j]);
		ans=max(ans,max(dp[i][0],dp[i][1]));
	}
	printf("%d\n",ans);
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值