[動的計画法]完全なバックパック:貯金箱(ちょうどいっぱい)

バックパックは完全に問題です:

重量(または占有スペース)がw1、W。、... Wnであるアイテムがn個あります。値はV1、2 .... nです。←
合計容量がWのナップザックが与えられた場合、各アイテムは次のことができます。全体として、またはそうでない場合にのみ、バックパックに入れてください。← Q:バックパックに入れるアイテムの総重量が正確にWになり、合計値が最大/最小に
なるように、バックパックに入れるアイテムを選択するにはどうすればよいですか?

バックパックを埋めるだけの問題は通常の01バックパックと同じですが、初期化が異なり、最終的には埋められるかどうかを判断します

dp [i] [j]:jで埋められた最初のiアイテムの最大値

初期化の問題:

最小値を見つけるために記入するだけです:dp-> inf、dp [0] = 0

最大値を見つけるために記入するだけです:dp->-inf、dp [0] = 0

理解する:

(1)初期化とは、バックパックにアイテムが入れられていない法的状態を指します。

①容量0のバックパックは何も入れず、値は0なのでdp [0] = 0

②容量が0でないバックパックは、何もロードせずに埋めることができず、未定義の状態になっているため、無限に割り当てる必要があります

(2)現在の法的な解は、以前の法的な状態から導出する必要があります。ループが終了した後もdp [m]がinfである場合、mに導出できる法的な状態がないことを意味します。つまり、 n個の数字で埋める。m

コード:

void input()
{
	cin>>e>>f;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>p[i]>>w[i];
	}
}
int main()
{
	input();
	memset(dp,inf,sizeof(dp));
	dp[0]=0;
	int v=f-e;
	for(int i=1;i<=n;i++)
	{
		for(int j=w[i];j<=v;j++)
		{
			dp[j]=min(dp[j],dp[j-w[i]]+p[i]);
		}
	}
	if(dp[v]==inf)
	{
		cout<<"impossible"<<endl;
	}
	else
	{
		cout<<dp[v]<<endl;
	}
  
}

おすすめ

転載: blog.csdn.net/m0_52043808/article/details/124001135