程序设计思维与实践 Week3 作业 (3/4/数据班)

A - 选数问题

Given n positive numbers, ZJM can select exactly K of them that sums to S. Now ZJM wonders how many ways to get it!

Input

The first line, an integer T<=100, indicates the number of test cases. For each case, there are two lines. The first line, three integers indicate n, K and S. The second line, n integers indicate the positive numbers.

Output

For each case, an integer indicate the answer in a independent line.

Example

Input
1
10 3 10
1 2 3 4 5 6 7 8 9 10
Output
4

Note

Remember that k<=n<=16 and all numbers can be stored in 32-bit integer

问题分析

题意是数列中选出K个数,让它们的和等于S。

01背包问题,每个数都有被选中和没被选中两种状态。使用递归的思路,如果一个数加入已经选好的数之后,总数不超过K,且和仍然小于等于S,这个数就可以被选,然后继续选判断它之后的数。

为了方便,把选中的数加入一个列表,然后,递归的时候,下次要求的和就应该减去这个数,下次开始的位置是这个数之后相邻的数。

#include <iostream>
#include <list>
using namespace std;
int tot = 0;
void selectNumbers(int i, int* arr, int n, int K, int sum, list<int>& res)
{
    if (res.size() == K && sum == 0)
    {
        tot++;
        return;
    }
    if (i >= n)
        return;
    if (res.size() > K || sum < 0)
        return;
    selectNumbers(i + 1, arr, n, K, sum, res);
    res.push_back(arr[i]);
    selectNumbers(i + 1, arr, n, K, sum - arr[i], res);
    res.pop_back();
}

int main()
{
    int* arr = new int[10];
    for (int i = 0; i < 10; ++i)
        arr[i] = 0;
    int T = 0, K = 0, S = 0;
    cin >> T;
    int a = 0, n = 0;
    for (int i = 0; i < T; ++i)
    {
        cin >> n >> K >> S;
        for (int j = 0; j < n; ++j)
            cin >> arr[j];
        tot = 0;
        list<int> res;
        selectNumbers(0, arr, n, K, S, res);
        cout << tot << endl;
    }
    delete[]arr;
    return 0;
}

B - 区间选点

数轴上有 n 个闭区间 [a_i, b_i]。取尽量少的点,使得每个区间内都至少有一个点(不同区间内含的点可以是同一个)

Input

第一行1个整数N(N<=100)

第2~N+1行,每行两个整数a,b(a,b<=100)

Output

一个整数,代表选点的数目

Examples

Input
2
1 5
4 6
Output
1
Input
3
1 3
2 5
4 6
Output
2

问题分析

区间可用结构体表示,存放左右两端点。

首先把结构按照左端点较大的优先的原则,用sort()排序。这样,如果取排名靠前左端点,则更有可能也在之后的区间内。记下当前区间左端点lastX,如果大于下一个区间的右端点,可以不再取下个区间,继续考虑其后的。

第一次提交的时候,由于没更新lastX的值,导致出错

#include <cstdio>
#include <algorithm>
using namespace std;

struct Inteval
{
    int x, y;
    Inteval() :x(0), y(0) {

    }
}I[105];
bool cmp(Inteval a, Inteval b)
{
    if (a.x != b.x)
        return a.x > b.x;
    else
        return a.y < b.y;
}
int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
    {
        scanf("%d%d", &I[i].x, &I[i].y);
    }
    sort(I, I + n, cmp);
    int ans = 1, lastX = I[0].x;
    for (int i = 1; i < n; ++i)
    {
        if (I[i].y < lastX) {
            lastX = I[i].x;
            ans++;
        }
            
    }
    printf("%d
", ans);
    return 0;
}

C - 区间覆盖(不支持C++11)

描述

数轴上有 n (1<=n<=25000)个闭区间 [ai, bi],选择尽量少的区间覆盖一条指定线段 [1, t]( 1<=t<=1,000,000)。
覆盖整点,即(1,2)+(3,4)可以覆盖(1,4)。
不可能办到输出-1

输入

第一行:N和T
第二行至N+1行: 每一行一个闭区间。

输出

选择的区间的数目,不可能办到输出-1

样例输入
3 10
1 7
3 6
6 10
样例输出
2

提示

这道题输入数据很多,请用scanf而不是cin

问题分析

这道题比较复杂,前面提交了9次都没有过,之后参考了别人写的文章,才得以通过。写完已经有一段时间,原文链接遗失了

首先看输入,既然输入的区间起点、终点都是整数,那么右端点小于1的和左端点大于t的区间都不可能覆盖[1, t],可以排除在外。对于有部分在[1, t]内的区间,不取外面的那一部分。

然后考察已经读入的区间,判断是否可以加入,如果可以,更新可覆盖的最大值,最后比较这个值和t

#include <cstdio>
#include <algorithm>
using namespace std;
struct Node {
    int l, r;
    bool operator<(const Node& node)const {
        return l < node.l;
    }
}temp[100010];
int main() {
    int n, t;
    scanf("%d%d", &n, &t);
    for (int i = 1; i <= n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        if (y < 1 || x > t) continue;
        if (x < 1) x = 1;
        if (y > t) y = t;
        temp[i].l = x; temp[i].r = y;
    }
    sort(temp + 1, temp + n + 1);
    if (temp[1].l != 1)
    {
        printf("-1
");
        return 0;
    }
    int s = 1;
    int ans = 0;
    int i = 1;
    while (i <= n && s <= t) {
        int Max = -1;
        if (temp[i].l > s) break;
        while (i <= n && temp[i].l <= s) {
            Max = max(Max, temp[i].r);
            i++;
        }
        if (Max != -1) {
            s = Max + 1;
            ans++;
        }
    }
    if (s <= t)
        ans = -1;
    printf("%d
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/master-cn/p/12529856.html