一、算法分析
完全背包套一个枚举,洛谷的题目翻译好像没说清是完全背包。详解看代码及注释。
二、代码及注释
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#define v first
#define h second
using namespace std;
//如果有大奶酪,则大奶酪必然在塔顶,因为大奶酪会影响塔中的所有奶酪
//且塔顶的其它大奶酪是不是大奶酪都无所谓了,因为压缩只算一次
//可以分成两种情况,第一种是塔顶没有大奶酪,则从所有小奶酪里面进行完全背包
//第二种是塔顶有大奶酪,则枚举放在塔顶的大奶酪,其余的奶酪对其高度取到原来的五分之四,然后进行完全背包
const int N=105;
const int M=1050;
int n,t,k;
typedef pair<int,int> PII;
PII w[N];
int big[N];
int cnt; //记录所有的大奶酪
int f[M];
int ans1,ans2;
int main(){
cin>>n>>t>>k;
for(int i=1;i<=n;i++){
scanf("%d%d",&w[i].v,&w[i].h);
if(w[i].h>=k) big[++cnt]=i;
}
//第一种情况,不选大奶酪
for(int i=1;i<=n;i++){
if(w[i].h>=k) continue;
for(int j=w[i].h;j<=t;j++){
f[j]=max(f[j],f[j-w[i].h]+w[i].v);
}
}
ans1=f[t];
//第二种情况,枚举最上面的大奶酪
for(int k=1;k<=cnt;k++){
memset(f,0,sizeof(f));
int p=big[k];
int m=t-w[p].h; //去掉大奶酪之后的剩余高度
if(m<0) continue;
for(int i=1;i<=n;i++){
for(int j=w[i].h*4/5;j<=m;j++){ //一定要注意这里的j初始值也要一并乘以4/5,调试了好久这个问题
f[j]=max(f[j],f[j-w[i].h*4/5]+w[i].v);
}
}
ans2=max(ans2,f[m]+w[p].v);
}
cout<<max(ans1,ans2);
return 0;
}
博客详细分析了USACO竞赛中的一道题目,涉及完全背包算法的应用。由于洛谷题目的翻译不明确,博主通过代码解释和注释清晰阐述了解题思路。
USACO10JANCheese Towers S&spm=1001.2101.3001.5002&articleId=107328089&d=1&t=3&u=4f0119450d774812a945dcb85248ca37)
440

被折叠的 条评论
为什么被折叠?



