补丁数组|Turing
Description
给定一个长度为l的有序非负整数列nums和一个整数n,最少需要添加多少个数可以使得[1,n]间的每一个数都可以被数列中
若干个数的和来表示。(数组中的元素不能重复使用)
输出最少需要添加多少个数字。
Input
共计两行。
第一行:两个整数l和n,分别代表数列nums的长度和整数n。(l不大于10^5,n不大于INT_MAX)
第二行:n个有序非负整数。(每个数不大于10^4)
Output
最少需要添加的数字个数。
输入样例 1
2 6
1 3
输出样例 1
1
Combinations of nums are [1], [3], [1,3], which form possible sums of: 1, 3, 4.
Now if we add/patch 2 to nums, the combinations are: [1], [2], [3], [1,3], [2,3], [1,2,3].
Possible sums are 1, 2, 3, 4, 5, 6, which now covers the range [1, 6].
So we only need 1 patch.
nums的组合是[1],[3],[1,3],它们形成可能的总和:1,3,4。
现在,如果我们将/补丁2添加到nums,则组合为:[1],[2],[3],[1,3],[2,3],[1,2,3]。
可能的总和是1,2,3,4,5,6,现在涵盖范围[1,6]。
所以我们只需要1个补丁。
输入样例 2
3 20
1 5 10
输出样例 2
2
The two patches can be [2, 4].
这两个补丁可以是[2,4]。
输入样例 3
3 5
1 2 2
输出样例 3
0
Language:
C++
思想
本题需采用贪心算法,试让使用的补丁最少,且能覆盖范围内的所有值,达到最简的目的。
最开始首先想象到的就是依次枚举题目给定数组之外的数,并判断是否满足条件。但是细读题目可以发现(l不大于10^5,
n不大于INT_MAX),l的范围可以接受,但是n的范围开数组是肯定超出题目限制了,会Runtime Error 或者是Time limit
exceed。
所以穷举是肯定不行了,我们就改变下思路,每次判断的位置后移,判断当前位置的数加上前置和是否会超出题目的n的
范围,如果没有,就继续,再判断一下是否这个和满足了当前范围,其中没有数的遗漏,如果有,就再申请一个适当的数
并进行判断。直到和sum>=n,就break
代码
#include<cstdio>
int main()
{
int n,i,j,l,nums[100005],sum=0,ans=0,wz=1;
scanf("%d%d",&l,&n);
for(i=1;i<=l;i++)
scanf("%d",&nums[i]);
for(;;)
{
if(sum>=n)
break;
for(;;)
if(wz<=l&&nums[wz]<=sum)
sum+=nums[wz++];
else
break;
if(wz<=l&&nums[wz]==sum+1)
wz++;
else
ans++;
}
printf("%d",ans);
}