zoukankan      html  css  js  c++  java
  • Codeforces Round #408 (Div. 2) E. Exam Cheating 滚动dp

    E. Exam Cheating
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    Zane and Zane's crush have just decided to date! However, the girl is having a problem with her Physics final exam, and needs your help.

    There are n questions, numbered from 1 to n. Question i comes before question i + 1 (1 ≤ i < n). Each of the questions cannot be guessed on, due to the huge penalty for wrong answers. The girl luckily sits in the middle of two geniuses, so she is going to cheat.

    However, the geniuses have limitations. Each of them may or may not know the answers to some questions. Anyway, it is safe to assume that the answers on their answer sheets are absolutely correct.

    To make sure she will not get caught by the proctor, the girl will glance at most p times, each time looking at no more than kconsecutive questions on one of the two geniuses' answer sheet. When the girl looks at some question on an answer sheet, she copies the answer to that question if it is on that answer sheet, or does nothing otherwise.

    Help the girl find the maximum number of questions she can get correct.

    Input

    The first line contains three integers np, and k (1 ≤ n, p ≤ 1, 000, 1 ≤ k ≤ min(n, 50)) — the number of questions, the maximum number of times the girl can glance, and the maximum number of consecutive questions that can be looked at in one time glancing, respectively.

    The second line starts with one integer r (0 ≤ r ≤ n), denoting the number of questions the first genius has answered on his answer sheet. Then follow r integers a1, a2, ..., ar (1 ≤ ai ≤ n) — the answered questions, given in a strictly-increasing order (that is, ai < ai + 1).

    The third line starts with one integer s (0 ≤ s ≤ n), denoting the number of questions the second genius has answered on his answer sheet. Then follow s integers b1, b2, ..., bs (1 ≤ bi ≤ n) — the answered questions, given in a strictly-increasing order (that is, bi < bi + 1).

    Output

    Print one integer — the maximum number of questions the girl can answer correctly.

    Examples
    input
    6 2 3
    3 1 3 6
    4 1 2 5 6
    output
    4
    input
    8 3 3
    4 1 3 5 6
    5 2 4 6 7 8
    output
    7
    Note

    Let (x, l, r) denote the action of looking at all questions i such that l ≤ i ≤ r on the answer sheet of the x-th genius.

    In the first sample, the girl could get 4 questions correct by performing sequence of actions (1, 1, 3) and (2, 5, 6).

    In the second sample, the girl could perform sequence of actions (1, 3, 5), (2, 2, 4), and (2, 6, 8) to get 7 questions correct.

    题目大意:有一个人要考试作弊, 她可以偷看左右两个人的试卷。但是她只能偷看p次,每次只能看一个人试卷上的连续的k个题目。总共有n道题目,给你左右两个人能做对的题目,求出她最大能做对几道题。

    样例解释:第一个样例:她共有2次偷看的机会,每次只能看3道题目,第一次偷看person1的(1,2,3), 第二次偷看person2的(4, 5, 6),可以作对的题目为(1, 3, 5, 6)共4道

    解析:这道题目可以看作区间覆盖,你有p个长度(0~k)的线段,尽量覆盖所有的规定的点即correct answer。

    我们可以用dp[i][j][x][y]来表示前i道题目使用了j次机会,其中person1还可以偷看连续的x道题目,peison2y道题目。

    如果我们现在在当前状态 dp[i][j][x-1][y-1],

    对于下一道题目我们可以选择使用对person1一次偷看的机会,会转移到dp[i+1][j+1][k-1][y] + (correct_i?)

    或者对person2使用,会转移到dp[i+1][j+1][x][k-1] + (correct_i?)

    或者不使用,会转移到dp[i+1][j][x][y] + (correct_i?)

    当然开1000*1000*50*50的空间是存不下的,所以要改成滚动数组

    另外对于时间的优化,如果我们可以覆盖整个区间(p > 2*ceil(n/k)), 那么我们覆盖最多的次数用2*ceil(n/k)就够了!

    时间复杂度 O(n*p*k^2) = O(n*(n/k)*k^2) = O(n^2*k) 

    #include <bits/stdc++.h>
    using namespace std;
    int a[1005], b[1005], dp[2][1005][55][55];
    int ab(int x) {
        if(x > 0) return x;
        return 0;
    }
    int main() {
        int n, p, k, r1, r2;
        scanf("%d%d%d", &n, &p, &k);
        if(p > 2*(n+k-1)/k) p = 2*(n+k-1)/k;
        scanf("%d", &r1);
        for(int i = 0, x; i < r1; i++) {
            scanf("%d", &x);
            a[x] = 1;
        }
        scanf("%d", &r2);
        for(int i = 0, x; i < r2; i++) {
            scanf("%d", &x);
            b[x] = 1;
        }
        memset(dp, -0x3f, sizeof(dp));
        dp[0][0][0][0] = 0;
        for(int i = 1; i <= n; i++) {
            for(int j = 0; j <= p; j++) {
                for(int x = 0; x < k; x++) {
                    for(int y = 0; y < k; y++) {
                        dp[i&1][j+1][k-1][ab(y-1)] = max(dp[i&1][j+1][k-1][ab(y-1)], dp[~i&1][j][x][y] + (a[i] || (y&&b[i])));
                        dp[i&1][j+1][ab(x-1)][k-1] = max(dp[i&1][j+1][ab(x-1)][k-1], dp[~i&1][j][x][y] + (b[i] || (x&&a[i])));
                        dp[i&1][j][ab(x-1)][ab(y-1)] = max(dp[i&1][j][ab(x-1)][ab(y-1)], dp[~i&1][j][x][y] + ((a[i]&&x)||(b[i]&&y)));
                    }
                }
            }
            memset(dp[~i&1], -0x3f, sizeof(dp[~i&1]));
        }
        int ans = 0;
        for(int j = 0; j <= p; j++) {
            for(int x = 0; x <= k; x++) {
                for(int y = 0; y <= k; y++)
                    ans = max(dp[n&1][j][x][y], ans);
            }
        }
        printf("%d
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    运维人员常用的linux命令汇总
    Linux 入侵痕迹清理技巧
    xshell突出显示
    Linux终端显示中文
    mysql8.0设uuid函数为默认值
    Linux使用NFS作为文件共享目录服务
    修改docker运行容器的映射端口
    Apache-kafka以及zookeepeer单机安装
    kafka-confluent管控中心安装
    记CentOS8下安装Docker
  • 原文地址:https://www.cnblogs.com/cshg/p/6708013.html
Copyright © 2011-2022 走看看