哈理工第四届校赛,,,F题,背包

http://acm.hrbust.edu.cn/contests/index.php?act=showproblem&cid=250&p=F

F.背包
Time Limit: 5000 MS Memory Limit: 32768 K
Total Submit: 117 (38 users) Total Accepted: 20 (20 users) Special Judge: No
Description

DS最近刚学会了背包。比如,给一个序列,问是否存在一个子集满足元素和为 X  DS 会用一种方法:

int dp[X+1];

dp[0] = 1;

for (int i = 0 ;i < n ; ++i)

for (int j = 0 ; j < X ; ++j)

if (dp[j] && j+a[i] <= X) dp[j + a[i]] = 1;

return dp[X];

xiaodao 觉得 DS 非常聪明,不过她想难为一下DS 她给了DS一个序列,序列中有 NN ≤107)个正整数,满足1A1 ,AiAi+1 ,Ai109
然后她让DS求这个序列的 “最小不可构造数,也就是最小的 Y 使得 Y 不能表示为序列的某个子集中所有元素的和。

Input

第一行是一个整数 T 代表数据组数,以下是 T 组数据。
每组数据第一行一个整数 N 代表本组数据一共有 N 个整数。
第二行 N 个整数 Ai 满足 1A1 ,AiAi+1 ,Ai109
所有的 N 加起来的和小于 107

Output

对于每组数据,输出一个整数 Y 代表本组数据的最小不可构造数。

Sample Input
3
3
1 2 4
2
2 100000
4
1 2 3 4
Sample Output
8
1
11
Hint

对于第一组样例

1 = 1 , 2 = 2  , 3 = 1 + 2 , 4 = 4 , 5 = 1 + 4 , 6 = 2 + 4 , 7 = 1 + 2 + 4

对于第三组样例

1 = 1 , 2 = 2 , 3 = 1 + 2 = 3 , 4 = 4 = 1 + 3 , 5 = 1 + 4 = 2 + 3 , 6 = 2 + 4 = 1 + 2 + 3 , 7 = 1 + 2 + 4 , 8 = 1 + 3 + 4 , 9 = 2 + 3 + 4 , 10 = 1 + 2 + 3 + 4

比赛时怎么写都超时,,,回来问问学长,原来如此啊!好精明的算法.

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define N 10000005
int n , a[N];
void work()
{
    int i , sum = 0;
    for (i = 0 ; i < n ; ++ i)
        scanf("%d",&a[i]);
    for (i = 0 ; i < n ; ++ i)
    {
        if (sum + 1 < a[i])//sum及其之前的数都能再构,若这个条件不成立,则sum~~sum+a[i]又都能表示了。若成了,则sum+a[i]+1这个数肯定是最小的不能表示的
            break;
        sum += a[i];
    }
    printf("%d\n" , sum + 1);
}
int main()
{
    int t;
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d",&n);
        work();
    }
    return 0;
}


你可能感兴趣的:(哈理工第四届校赛,,,F题,背包)