这个题是一道奇怪的DP,大奶酪会把它下面的奶酪压扁(其实就是压成(4/5)),
如果说不考虑大奶酪会把其他的奶酪压扁,那么我们得到一个显然的规律:
塔中的奶酪可以任意交换顺序。
那么考虑我们要放一块大奶酪,把它放在那里好呢?肯定是最上面,(因为会把除它之外的所有奶酪压扁)
可是有的大奶酪太占空间了,是不能放的,而且我们又不能在DP的过程中判断奶酪的大小情况,
于是我想到了先确定大小情况,再DP,
先枚举放哪一块大奶酪(在最顶部),然后把剩下的奶酪高度都换算一下,跑背包。
对了,不要忘了枚举一块大奶酪都不放的情况,此时注意在DP过程中,不要涉及到任何一块大奶酪(开一个flag数组标记一下),
另外也许可以这么做:
将奶酪排序,(大奶酪在前),在DP的过程中判定是否有大奶酪,
但是这种做法在高度的控制上可能比较难,我没有尝试
下面是我的代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
int n,k,t;
inline int ra()
{
int x=0;char ch=getchar();int flag=1;
while(ch>'9'||ch<'0'){if(ch=='-')flag=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x*=10;x+=ch-'0';ch=getchar();}
return flag*x;
}
int h[500];
int v[500];
int ans;
bool big[500];
int dp[2000];
int main()
{
n=ra();t=ra();k=ra();
for(int i=1;i<=n;i++)
{
v[i]=ra();h[i]=ra();
if(h[i]>=k)big[i]=1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=t;j++)
{
if(j>=h[i]&&!big[i])dp[j]=max(dp[j],dp[j-h[i]]+v[i]);
// else dp[j]=dp[i-1][j];
}
ans=max(ans,dp[t]);
for(int now=1;now<=n;now++)
if(big[now])
{
memset(dp,0,sizeof(dp));
int nowt=((t-h[now])*5)/4;
for(int i=1;i<=n;i++)
for(int j=1;j<=nowt;j++)
{
if(j<h[i])dp[j]=dp[j];
else dp[j]=max(dp[j],dp[j-h[i]]+v[i]);
}
ans=max(ans,dp[nowt]+v[now]);
}
cout<<ans<<endl;
return 0;
}