【搜索与回溯】 NOIP2001第四题 装箱问题

题目友链☟

你谷友链
JZOJ
一本通OJ

洛谷标签: 动 态 规 划 , 递 归 , N O I p 普 及 组 2001 ( 或 之 前 ) 动态规划,递归,NOIp普及组2001(或之前) NOIp2001()
但我觉得,还是可以分为搜索与回溯

题目描述

有一个箱子容量为 V V V(正整数, 0 ≤ V ≤ 20000 0 ≤V≤20000 0V20000),同时有 n n n个物品( 0 < 300 < n ≤ 30 0<300<n≤30 0<300<n30),每个物品有一个体积(正整数)。

要求 n n n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。

输入输出格式

输入格式:
1 1 1个整数,表示箱子容量
1 1 1个整数,表示有 n n n个物品
接下来 n n n行,分别表示这 n n n个物品的各自体积
输出格式:
1 1 1个整数,表示箱子剩余空间。

输入输出样例

输入样例# 1 1 1:

24
6
8
3
12
7
9
7

输出样例# 1 1 1

0

解析:

也许很多大佬都觉得,这种题目应该用动态规划来做,但是我写一个搜索的题解(不要问为什么,因为我蒟)。。。
这个题目其实是有点像01背包的。
在搜索中定义一个 s u m sum sum,用来储存现在的箱子剩余体积,到时候可以拿总量去减(逆向思维)既然有了这个这个 s u m sum sum,出口就好找了,定义 a n s ans ans(一开始为零(初始化,不多说)),当 a n s ans ans<总体积减去 s u m sum sum时, a n s ans ans就等于这个值。每次都进行这个搜索,如果有某一个物品的体积≤ s u m sum sum时,就拿sum去减即可。输出的时候要注意,不是仅仅输出 a n s ans ans,而是用总重- a n s ans ans,就可以完美结束了。

下面,就该上代码了:

#include
using namespace std;
int a[1001];
int n,c,ans;//ans表示已经用完的空间
void s(int x,int sum){//定义两个值,一个表示当前箱子剩余体积,一个记数
	if (x==n+1){
		if (ans<c-sum)
			ans=c-sum;//当ans<总数-剩余体积时,ans就有值了
		return;
	}
	else
	{
		s(x+1,sum);//下一次搜索
		if (a[x]<=sum)
			s(x+1,sum-a[x]);
	}
}
int main(){
	cin>>c>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	ans=0;//初始化
	s(1,c);//从总体积开始搜起
	cout<<c-ans<<endl;//上面说过的,注意这里
	return 0;
}

不要老是Ctrl + C 和Ctrl + V啦
如有雷同,纯属巧合!

你可能感兴趣的:(DFS,洛谷,JZOJ,NOIP2001,深度优先搜索,YBT)