• 部分和问题---多重部分和问题---动态规划


    一:部分和问题

    给定整数a1、a2、.......an,判断是否可以从中选出若干数,使它们的和恰好为K。

    输入:

    n=4

    a={1,2,4,7}

    k=13

    输出:

    Yes(13=2+4+7)

    书中带来是DFS搜索,相对比较简单

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    int n = 4;
    int a[] = { 1,2,4,7 };
    int k = 15;
    
    bool dfs(int i,int sum) {
        if (i == n)return sum == k;
        if (dfs(i + 1, sum))return 1;
        if (dfs(i + 1, sum + a[i]))return 1;
        return false;
    }
    
    int main() {
        cout << dfs(0, 0) << endl;
        return 0;
    }
    

    如果要求保存相加的每一个数,可以这样实现:

    #include <iostream>
    #include <vector>
    using namespace std;
    int a[4]={1,2,4,7},k;
    vector<int> ans;
    void dfs(int i,int sum)
    {
    	if(i==4){
    		if(sum==k)
    	   	{
       			for(int i=0;i!=ans.size();i++)cout<<ans[i]<<" ";
    			cout<<endl;
    			return ;
       		}
       		else 
    		 return ;
    	}
    	dfs(i+1,sum);
    	ans.push_back(a[i]);
    	dfs(i+1,sum+a[i]);
    	ans.pop_back();
    	return ;
    }
    int main()
    {
    	 k=7;
    	 dfs(0,0);
    }
    

    第二:多重部分和

    n种大小不同的数字 ai,每种各mi个,判断是否可以从这些数字之中选出若干个使他们的和恰好为K。

    输入:

    n=3;

    a={3,5,8}

    m={3,2,2}

    K=17

    输出:

    Yes(3*3+8)

    思路:

    这个问题可以用DP来求解: dp[i][j] := 用前i种数字是否能加和成j

    #include <iostream>
    #include <vector>
    using namespace std;
    int n,K;
    const int maxn=100;
    const int maxk=100000;
    int a[maxn],m[maxn];
    bool dp[maxn][maxk];
    int main()
    {
    	cin>>n;
    	for(int i=0;i<n;i++)
    		cin>>a[i];
    	for(int i=0;i<n;i++)
    		cin>>m[i];
    	cin>>K;
    	dp[0][0]=1;
    	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])cout<<"yes"<<endl;
    	else cout<<"no"<<endl;
    	//cout<<dp[n][K]<<endl;
    	return 0;				
    }
    

    将这个问题稍加变形:求解从这些数字中选取若干能恰好加和成K的方法数。

    #include <iostream>
    #include <vector>
    using namespace std;
    int n,K;
    const int maxn=100;
    const int maxk=100000;
    int a[maxn],m[maxn];
    int dp[maxn][maxk];
    int main()
    {
    	cin>>n;
    	for(int i=0;i<n;i++)
    		cin>>a[i];
    	for(int i=0;i<n;i++)
    		cin>>m[i];
    	cin>>K;
    	dp[0][0]=1;
    	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])cout<<"yes"<<endl;
    	else cout<<"no"<<endl;*/
    	cout<<dp[n][K]<<endl;
    	return 0;				
    }
    
  • 相关阅读:
    解决CollectionView TableView reloadData或者reloadSections时的刷新的闪烁问题
    HTTP请求头
    Fastlane 使用笔记
    python-函数式编程
    python-高级特性
    python基础使用
    python基础-函数02
    python基础-函数01
    python基础
    Linux基础
  • 原文地址:https://www.cnblogs.com/RioTian/p/12989880.html
Copyright © 2020-2023  润新知