• dp,优化记录,打扑克


    Contest (nefu.edu.cn)

    Problem:F
    Time Limit:1000ms
    Memory Limit:65535K

    Description

    一天,明明在玩纸牌游戏。
    游戏规则是:一共有 n 张牌,每张牌上有一个花色 c 和一个点数 v,花色不超过 k 种。将这些牌依次放入一列牌的末端。若放入之前这列牌中已有与这张牌花色相同的牌,你可以选择将这张牌和任意一张花色相同的牌之间的所有牌全部取出队列(包括这两张牌本身),并得到与取出的所有牌点数和相同的分数。现在已知 明明 把这 n 张牌放入队列的顺序,求他最多能得多少分。
    
    输入顺序即为 明明 放入队列的顺序。即,ci表示第 i 张放入的牌的花色,vi表示第 i 张放入的牌的点数。
    

    Input

    第一行两个整数 n,k。(1 
    

    Output

    输出一行一个整数,表示最多能得到的分数。

    Sample Input

    7 3
    1 2 1 2 3 2 3
    1 2 1 2 3 2 3
    

    Sample Output

    13

    Hint

     样例解释 1
    第 1 步,向队列加入 1。现在的队列:1
    第 2 步,向队列加入 2。现在的队列:1,2
    第 3 步,向队列加入 1。现在的队列:1,2,1
    第 4 步,向队列加入 2,取出 2,1,2。现在的队列:1
    第 5 步,向队列加入 3。现在的队列:1,3
    第 6 步,向队列加入 2。现在的队列:1,3,2
    第 7 步,向队列加入 3,取出 3,2,3。现在的队列:1

    题解:dp,优化记录

    这道题不难想到用dp,状态转移方程也很容易想到

    三个数组,col:花色,sum:前缀和,MAX:f[i-1]-sum[i-1];

    f[i]=f[i-1];

    if(col[i]==col[j])

    f[i]=max(f[i],f[j-1]+sum[i]-sum[j-1])

    但我们发现这个需要两重循环,会爆时间,所以需要优化一下

    这里提供一个方法:
    我们使用数组 MAX[col[i]] 记录已经出现过的花色为 col[i] 的 f[i-1]-sum[i-1]

    这样当下一个花色同样为 col[i] 的花色出现时,当前的 col[i] 既是那时候的 col[j]

    而MAX里的内容也就是那时候的 f[j-1] -sum[j-1]

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. #include
    16. using namespace std;
    17. typedef long long LL;
    18. const int N = 2e5 + 5;
    19. int n, k;
    20. LL sum[N], col[N], MAX[N];
    21. LL f[N];
    22. int main() {
    23. scanf("%d%d", &n, &k);
    24. for (int i = 1; i <= n; i++) {
    25. scanf("%lld", & col[i]);
    26. }
    27. for (int i = 1; i <= n; i++) {
    28. scanf("%lld", &sum[i]);
    29. sum[i] += sum[i - 1];
    30. }
    31. memset(MAX, 192, sizeof(MAX));
    32. for (int i = 1; i <= n; i++) {
    33. f[i] = max(f[i - 1], MAX[col[i]] + sum[i]);
    34. MAX[col[i]] = max(MAX[col[i]], f[i - 1] - sum[i - 1]);
    35. }
    36. printf("%lld\n", f[n]);
    37. return 0;
    38. }

     

  • 相关阅读:
    力扣(LeetCode)82. 删除排序链表中的重复元素 II(C语言)
    C#实现图片对比-支持图片旋转
    C#8.0本质论第十章--合式类型
    详解memcpy和memmove函数的使用
    03-视口
    硬件开发笔记(十九):Altium Designer 21软件介绍和安装过程
    【K8S运维实操】关于docker和k8s的一些命令、镜像制作的实操
    k8s 怎么精准获取deployment关联的pods?
    死锁的发生与避免
    开源模型应用落地-业务优化篇(七)
  • 原文地址:https://blog.csdn.net/Landing_on_Mars/article/details/132817988