多重部分和问题

有n种大小不同的数字,各种各mi个,判断是否可以从这些数字之中选出若干个使他们的和恰好为K。
输入:
第一行为n
第二行为n种数字
第三行为这n中数的个数
第四行为K

输出:
可以 输出”yes”

不可以 输出“no”

样例:

3
3 3
5 2
8 2
17

法一:bool值判断不着重讲

#include<iostream> 
#include <cstdio>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 1010;
bool dp[maxn][maxn];
int a[maxn], m[maxn];
int n, K;
int main()
{
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
	}
	for (int i = 0; i < n; i++)
	{
		cin >> m[i];
	}
	memset(dp, false, sizeof(dp));
	dp[0][0] = true;
	cin >> K;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j <= K; j++)
		{
			for (int k = 0; k*a[i] <= j || k <= m[i]; k++)//
			{
				dp[i + 1][j] |= dp[i][j - k*a[i]];//存在性问题,不断取或看看能否到dp[n][K].
			}
		}
	}
	if (dp[n][K])
		cout << "YES" << endl;
	else
		cout << "No" << endl;
    return 0;
}

法二:优化为一维数组:状态转移方程
dp[i+1][j] = 
            1.m[i](前i-1个数加和已经得到了K所以不需要i)(dp[i][j]>=0)
            2.-1(两种情况1.加a[i]越界了大于k;
                         2如果在用前i个数能凑成和j-a[i-1].但m[i-1]的数目不够了
                         或无法用前i个数凑成和j - a[i-1])
            (j<a[i]或dp[i+1][j-a[i]]<=0)
            3.dp[i+1][j-a[i]]-1(其他情况)(前i格数加和可以得到j-a[i-1],所以只需数目减一即可。

代码:

#include<iostream> 
#include <cstdio>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 1010;
bool dp[maxn];
int a[maxn], m[maxn];
int n, K;
/* 状态转移方程:
dp[i+1][j] = 
			1.m[i](前i-1个数加和已经得到了K所以不需要i)(dp[i][j]>=0)
			2.-1(两种情况1.加a[i]越界了大于k;
						 2如果在用前i个数能凑成和j-a[i-1].但m[i-1]的数目不够了
						 或无法用前i个数凑成和j - a[i-1])
			(j<a[i]或dp[i+1][j-a[i]]<=0)
			3.dp[i+1][j-a[i]]-1(其他情况)(前i格数加和可以得到j-a[i-1],所以只需数目减一即可。			
*/
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;
	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)
	{
		cout << "YES" << endl;
	}
	else
	{
		cout << "No" << endl;
	}
}

猜你喜欢

转载自blog.csdn.net/fighting_yifeng/article/details/81434662
今日推荐