再帰5:[SSL] 1169ボクシングの問題
トピック:
容量がV(正の整数、0 <= V <= 20000)のボックスがあり、n個のアイテム(0 <n <= 30、各アイテムにはボリューム(正の整数)があります)があります。
n個のアイテムのうち、ボックスの残りのスペースを最小限に抑えるために、任意の数のアイテムをボックスに入れることができる必要があります。
入力例
24
6
8
3
12
7
9
7
出力サンプル
0
アイデア:
このトピックは実際には良い考えですが、データが大きすぎるため、最適化に注意を払う必要があります。
よく考えてみると、箱に入れる方法が2つしかないことを見つけるのは難しいことではありません。例えば、置く使用1,0入れないし3つのボックスがあると仮定すると、8つの方法があります。
111
110
101
100
011
010
001
000
我々は、N個のボックスがパワーN植栽方法2を有していると結論することができるようにします。
ただし、最大nは30、2 ^ 30は10億以上です。1つずつ試してみると、必然的にタイムアウトになるので、最適化する必要があります。再帰をツリーと見なすと、条件が見つかった場合、枝や葉の一部を切り取ることができるため、タイトルにスペースが記載されているため、実行回数を大幅に減らすことができます。ボックスをできるだけ減らす必要があるので、各再帰を判断するとき、私の残りのすべてのボリュームとボックス内のスペースがこれまでに見つけた最大値以下である限り、この再帰は終了する可能性がありますそして前のレベルに戻ります。
コード:
#include<bits/stdc++.h>
using namespace std;
int n,v,a[50],h,b[50];
void dg(int p,int s,int sy)
{
if(p>n)
{
h=max(h,s);
return ;
}
if(s+b[n]-b[p-1]<=h)
return ;
if(sy>=a[p])
dg(p+1,s+a[p],sy-a[p]);
dg(p+1,s,sy);
}
int main()
{
cin>>v>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i]=b[i-1]+a[i];
}
dg(1,0,v);
cout<<v-h;
return 0;
}