【USACO10JAN】Cheese Towers S 奶酪塔 (背包dp)
一种思路奇特的做法。
看到题目容易联想到背包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 ) egin{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_jgeq K) end{cases} {dp(i,0)=max(dp(i−hj,0)+vj) (hj<K)dp(i,1)=max(dp(i−hj,0)+vj) (hj≥K)
然后对于 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(i−54hj,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
",ans);
return 0;
}