最小不可组成和:两种情况:
1.[min,max] 如果有一个数不能被某个子集得到,求:最小的那个数
arr[3,2,5] sum={2,3,5,5,7,8,10} 少{4,6,9} 返回4
2.[min,max] 如果都有,那么max+1是arr最小不可组成和
arr[1,2,4] sum={1,2,3,4,5,,6,7} 返回8
解法:暴力递归: 略
动态规划:背包:bool二维表
1.行arr ;列 sum+1; dp[i][j]: arr[0..i]自由选择能否累加出j来
2.三种情况
2.1.位置对应的数肯定为true
2.2. 第二行开始,只选前一个数 dp[i-1][j]
2.3. 当前数和前一个数 dp[i-1][j-arr[i]]
int unformedSum(vci arr)
{
int sum = 0;
int m_min = RAND_MAX;//
for (int i = 0; i != arr.size(); i++)//提前要求sum 和最小值
{
sum += arr[i];
m_min = min(m_min, arr[i]);
}
cout << "m_min=" << m_min << endl;
cout << "sum" << sum << endl;
int N = arr.size();
int row = arr.size();//3;//行
int col = sum+1;//10;//列
vector<vector<bool> > vcidp(N); //这个N一定不能少
for (int i = 0; i < row; i++)
{
vcidp[i].resize(col);
}
vcidp[0][arr[0]] = true; //第0行全是true 第0列 全是false
for (int i = 1; i < N; i++) //填二维表
{
for (int j = 1; j <= sum; j++)
{
if (arr[i] == j) //背包问题三个条件 1.本身
{
vcidp[i][j] = true;
}
else if (vcidp[i - 1][j]) //2.上面的位置
{
vcidp[i][j] = true;
}
else if (j - arr[i] >= 0 && vcidp[i - 1][j - arr[i]])3.上面位置的偏移量 前面的条件表示不越界,后面是偏移量
{
vcidp[i][j] = true;
}
}
}
//最后一行的值选最小
//int ans = m_min;
for (int ans=m_min; ans <= sum; ans++)
{
if (!vcidp[N-1][ans]) //最后一行 最小的不能组成的,就是数组中是false 的返回
{
return ans;//第一种情况,最小的一个
}
}
return sum + 1;// 第二种情况 max+1
}
void smallestUnFormedSum_main()
{
cout << "****smallestUnFormedSummain*********" << endl;
vci vci1;
vci1.insert(vci1.begin(), { 3, 2, 5 });
cout << "arr[3, 2, 5] 返回4---" << unformedSum4(vci1)<< endl;
vci vci2;
vci2.insert(vci2.begin(), { 1, 2, 4 });
cout << "arr[1, 2, 4] 返回8---" << unformedSum4(vci2) << endl;
}