[Dynamic programming] 01 Knapsack problem: cat and dog war

A pile of numbers is divided into two groups
(1) the number of each group can only differ by one
(2) the difference between the sum of each group is as small as possible
Input: n, n numbers
Output: the sum of each group

01 Backpack:

The sum of all numbers is sum. If you want the sum of the two sets of numbers to be as small as possible, then the two sets of numbers should be as close to sum/2 as possible.


If the number is even, choose n/2 numbers, and the capacity is sum/2, so that the value is the largest. If the
number is odd, choose n/2 numbers, and the capacity is sum/2, which is the largest value.
Therefore, among the n numbers, Choose n/2 numbers so that their sum is the largest and does not exceed sum/2

dp[i][j][k]: Select k numbers from the first i numbers so that their sum does not exceed j and the maximum
dp[i][j][k]=max(dp[i-1][j] [k],dp[i-1][jw[i]][k-1]+w[i])
rolling array:
dp[j][k]=max(dp[j][k],dp[ jw[i]][k-1]+w[i]) 

code

#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];
}

Guess you like

Origin blog.csdn.net/m0_52043808/article/details/123978251