题目名称:装箱问题
来源:2011年NOIP普及组

链接

博客链接

题目链接

题目内容

题目描述

有一个箱子容量为\(V\)(正整数,\(0\le V\le20000\)),同时有\(n\)个物品(\(0<n\le30\)),每个物品有一个体积(正整数)。
要求\(n\)个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。

格式

输入

\(1\)个整数,表示箱子容量

\(1\)个整数,表示有\(n\)个物品

接下来\(n\)行,分别表示这\(n\)个物品的各自体积

输出

\(1\)个整数,表示箱子剩余空间。

样例

输入

24
6
8
3
12
7
9
7

输出

0

前缀知识

题解

这是一道01背包裸题,先进行01背包,在找到比\(v\)小但是可以得到的数,输出\(v\)与这个数的差。

//C++
#include<bits/locale_facets.h>
#include<bitset>
#include<stdio.h>
#define downto(name,i,u,d) for(name i=u;i>=d;i--)
inline void output(long long o);
inline long long input();
std::bitset<20001>full;
int main(){
    short v=input(),n=input(),volume;
    full[0]=true;
    while(n--){
        volume=input();
        downto(short,i,v,volume)full[i]=full[i]|full[i-volume];
    }for(short i=0;;i++)
    if(full[v-i])return output(i),0;
}inline void output(long long o){
    if(o<0)putchar('-'),o=-o;
    if(o>=10)output(o/10);
    putchar(o%10^'0');
}inline long long input(){
    bool minus=false;
    char now=getchar();
    long long i=0;
    for(;!isdigit(now);now=getchar())
    if(now=='-')minus=!minus;
    for(;isdigit(now);now=getchar())i=(i<<3)+(i<<1)+(now^'0');
    return minus?-i:i;
}
//pascal
type box=0..20000;
var
    i,n:1..30;
    j,v,volume:box;
    full:array[box] of boolean;
begin
    readln(v);
    readln(n);
    full[0]:=true;
    for j:=1 to v do full[j]:=false;
    for i:=1 to n do begin
        readln(volume);
        for j:=v downto volume do full[j]:=full[j] or full[j-volume];
    end;for j:=0 to v do
    if full[v-j] then break;
    write(j);
end.
02-13 21:13