[USACO4.1] 麦香牛块Beef McNuggets
题目描述
农夫布朗的奶牛们正在进行斗争,因为它们听说麦当劳正在考虑引进一种新产品:麦香牛块。奶牛们正在想尽一切办法让这种可怕的设想泡汤。奶牛们进行斗争的策略之一是“劣质的包装”。“看,”奶牛们说,“如果你只用一次能装 3 3 3 块、 6 6 6 块或者 10 10 10 块的三种包装盒包装麦香牛块,你就不可能满足一次只想买 1 1 1 、 2 2 2 、 4 4 4 、 5 5 5 、 7 7 7 、 8 8 8 、 11 11 11 、 14 14 14 或者 17 17 17 块麦香牛块的顾客了。劣质的包装意味着劣质的产品。”。
你的任务是帮助这些奶牛。给出包装盒的种类数 N ( 1 ≤ N ≤ 10 ) N(1 \le N \le 10) N(1≤N≤10) 和 N N N 个代表不同种类包装盒容纳麦香牛块个数的正整数 ( 1 ≤ i ≤ 256 ) (1 \le i \le 256) (1≤i≤256),输出顾客不能用上述包装盒(每种盒子数量无限)买到麦香牛块的最大块数。如果所有购买方案都能得到满足或者不存在不能买到块数的上限,则输出 0 0 0。不能买到的最大块数(倘它存在)不超过 2 × 1 0 9 2\times 10^9 2×109。
输入格式
第 1 1 1 行:包装盒的种类数 N N N。
第 2 2 2 行到 N + 1 N+1 N+1 行:每个种类包装盒容纳麦香牛块的个数。
输出格式
输出文件只有一行数字:顾客不能用包装盒买到麦香牛块的最大块数或 0 0 0(如果所有购买方案都能得到满足或者顾客不能买到的块数没有上限)。
样例 #1
样例输入 #1
3
3
6
10
样例输出 #1
17
提示
题目翻译来自 NOCOW。
USACO Training Section 4.1
思路
- 对于这种什么能凑数,什么不能凑数(就是一个数能否被给定的数表示)这类题目,我们可以用完全背包(
bool
类型的)。 - 其次,这个完全背包的
f[i]
如果是true
的话,说明i
能被给定的数表示。 - 之后我们就倒着枚举(因为题目说要最大嘛)
- 细节:这边得知道一下
f[i]
的数组具体开多大,我们具体可以看:
代码
//这种配对问题跟那个包子凑数很像
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 230,M = 1e5+10;
int w[N],f[M+2];
int n,t;
int ans;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>w[i];
}
//w+k,w+2k,w+3k...能被表示出来
f[0]=1;
for(int i=1;i<=n;i++){
for(int j=w[i];j<=M;j++){//完全背包
f[j]|=f[j-w[i]];
}
}
for(int i=M;i>=0;i--){
if(!f[i]){
ans=i;
break;
}
}
if(ans==100009){
ans=0;
}
cout<<ans;
return 0;
}