链接:https://www.nowcoder.com/questionTerminal/f5368cd8008d41f58b2da7ced2f4d809
来源:牛客网
给定一个正数数组arr,其中所有的值都为整数,以下是最小不可组成和的概念
把arr每个子集内的所有元素加起来会出现很多值,其中最小的记为min,最大的记为max
在区间[min, max]上,如果有数不可以被arr某一个子集相加得到,那么其中最小的那个数是arr的最小不可组成和
在区间[min, max]上,如果所有的数都可以被arr的某一个子集相加得到,那么max+1是arr的最小不可组成和
请写函数返回正数数组arr的最小不可组成和
输入描述:
第一行一个整数N,表示数组长度。
接下来一行N个整数表示数组内的元素。
输出描述:
输出一个整数表示数组的最小不可组成和
示例1
输入
3
2 3 9
输出
4
示例2
输入
3
1 2 4
输出
8
说明
3 = 1 + 2
5 = 1 + 4
6 = 2 + 4
7 = 1 + 2 + 4
思路:这个题和【数字和为sum的方法数】这个题很像,都是背包问题的变形,用动态规划做。
代码:
#include<iostream>
#include<vector>
using namespace std;
int Min_No_Sum(vector<int> v, int n)
{
int max = v[0];
int min = v[0];
for (int i = 1; i < n; i++)
{
if (v[i] < min)
min = v[i];
max += v[i];
}
vector<vector<int>> buf(n + 1, vector<int>(max + 1, 0));
for (int i = 0; i < n + 1; i++)
buf[i][0] = 1;
for (int i = 1; i < n + 1; i++)
{
for (int j = 1; j < max + 1; j++)
{
if (v[i - 1] > j || buf[i - 1][j] != 0)
buf[i][j] = buf[i - 1][j];
else
buf[i][j] = buf[i - 1][j - v[i - 1]];
}
}
for (int i = min; i < max + 1; i++)
{
if (buf[n][i] == 0)
return i;
}
return max + 1;
}
int main()
{
int n;
while (cin >> n)
{
vector<int> v(n);
for (int i = 0; i < n; i++)
cin >> v[i];
cout << Min_No_Sum(v, n) << endl;
}
return 0;
}