(2.15) Multiple parts and problems

Title (DP)

Insert picture description here
Insert picture description here

Code

How to define the recurrence relationship will affect the final complexity.
Solution 1:
dp[i+1][j] := whether the first i types of numbers can be added to j.
If we want to use the first i types of numbers to add up to j, we Need to use the first i-1 types of numbers to add up to one of j, ja[i],… ja[i]*m[i]

Recurrence relationship:
Insert picture description here

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

const int MAX_N = 100;
const int MAX_K = 100000; 
bool dp[MAX_N+1][MAX_K+1]; // DP数组 

//输入 
int n = 3;   // 数组的长度 
int K = 17;  // 目标和数 
int a[3] = {
    
    3,5,8};  // 不同的数据 
int m[3] = {
    
    3,2,2};  // 不同数据的个数 

void solve(){
    
    
	dp[0][0] = true;
	for(int i = 0 ; i < n ; i ++){
    
    
		for(int j = 0 ; j <= K ; j ++){
    
    
			for(int k = 0 ; k <= m[i] && k*a[i] <= j ; k ++){
    
    
				dp[i+1][j] |= dp[i][j - k*a[i]];
			}
		}
	}
	if(dp[n][K]) printf("Yes\n");
	else printf("No\n"); 
} 

int main(){
    
    	
	solve(); 
	return 0;
}

Scheme 2: O(nK)
DP calculating bool will waste time. In this scheme, we not only find out whether the sum of the target can be obtained, but also calculate how many a[i] is left when we get it. To reduce complexity.
dp[i+1][j] := How many i-th kinds of numbers can be left when adding the previous i kinds of numbers to get j (-1 if i cannot be added together)

If the sum of the first i-1 numbers can get j, the i-th number can leave m[i],
if the i-th number is added and ja[i], the i-th number still has k( If k>0), the number of i-th species can be left k-1 when the number of i species is added to j.
Insert picture description here

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

const int MAX_K = 100000; 
int dp[MAX_K+1]; // DP数组 

//输入 
int n = 3;   // 数组的长度 
int K = 17;  // 目标和数 
int a[3] = {
    
    3,5,8};  // 不同的数据 
int m[3] = {
    
    3,2,2};  // 不同数据的个数 

void solve(){
    
    
	memset(dp, -1, sizeof(dp));
	dp[0] = 0;
	for(int i = 0 ; i < n ; i ++){
    
    
		for(int j = 0 ; j <= K ; j ++){
    
    
			if(dp[j] >= 0)
				dp[j] = m[i];
			else if(j < a[i] || dp[j - a[i]] <= 0)
				dp[j] = -1;
			else
				dp[j] = dp[j - a[i]] - 1;
		}
	}
	if(dp[K] >= 0) printf("Yes\n");
	else printf("No\n"); 
} 

int main(){
    
    	
	solve(); 
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_36321330/article/details/106848986