[動的計画法]01ナップサック問題:猫と犬の戦争

数字の山は2つのグループに分けられます
(1)各グループの数は1つだけ異なることができます
(2)各グループの合計の差は可能な限り小さい
入力:n、nの数字
出力:それぞれの合計グループ

01バックパック:

すべての数値の合計は合計です。2セットの数値の合計をできるだけ小さくしたい場合は、2セットの数値をできるだけsum/2に近づける必要があります。


数が偶数の場合はn/2の数を選択し、容量はsum / 2であるため、値が最大になります。
数が奇数の場合はn / 2の数を選択し、容量はsum/2です。最大値。
したがって、n個の数値の中から、合計が最大になり、sum/2を超えないようにn/2個の数値を選択します。

dp [i] [j] [k]:最初のi個の数からk個の数を選択して、それらの合計がjを超えないようにし、最大
dp [i] [j] [k] = max(dp [i-1] [ j] [k]、dp [i-1] [jw [i]] [k-1] + w [i])
ローリングアレイ:
dp [j] [k] = max(dp [j] [k]、 dp [jw [i]] [k-1] + w [i]) 

コード

#include<iostream>
#include<cstring>
using namespace std;
int n;
int w[201];
int dp[10000][201];
int main()
{
	memset(dp,0,sizeof(dp));
	cin>>n;
	int sum=0;
	for(int i=1;i<=n;i++){
		cin>>w[i];
		sum+=w[i];
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=sum/2;j>=w[i];j--){
			for(int k=1;k<=n/2;k++){
				dp[j][k]=max(dp[j][k],dp[j-w[i]][k-1]+w[i]);
			}
		}
	}
	cout<<dp[sum/2][n/2];
}

おすすめ

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