[NOIP普及组2011]装箱问题


题目名称:装箱问题
来源: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.
posted @ 2019-09-28 15:05  ANY_HOW  阅读(245)  评论(0编辑  收藏  举报