zoukankan      html  css  js  c++  java
  • codeforces 467C.George and Job 解题报告

    题目链接:http://codeforces.com/problemset/problem/467/C

    题目意思:给出一条含有 n 个数的序列,需要从中找出 k 对,每对长度为 m 的子序列,使得 找出来的k对序列的总和相同。注意,同一个数不能在两个子序列中。

        首先用了很暴力的做法,赛后发现过不了test 5 的时候,就知道需要用到 dp 来做了。看了这个人的提示:

        

        其实看完这个状态转移方程,就觉得这题不太难了。

        dp[i][j]: 前 i 个数中,选择 j pairs 可以获得的最大和。

        那么对于第 i 个数来说,有不选和选择的两种情况。如果不选第 i 这个数 ,即dp[i-1][j],表示前 i 个数,选择 j pairs 获得的最大和 = 前i-1个数中选择 j pairs 可以获得的最大和;如果选第 i 个数,状态就转移到 dp[i-m][j-1] + sum[i] - sum[i-m],这个 sum[i]- sum[i-m] 会成为新的一个pair,前面那个第 i-m 个数就不要选。

         虽然运行时间有点慢,但好在非常容易理解。

        

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cstring>
     5 using namespace std;
     6 
     7 typedef long long ll;
     8 const int maxn = 5000 + 10;
     9 ll sum[maxn], dp[maxn][maxn], p;
    10 
    11 int main()
    12 {
    13     int n, m, k;
    14     while (scanf("%d%d%d", &n, &m, &k) != EOF)
    15     {
    16         scanf("%lld", &p);
    17         sum[1] = p;
    18         for (int i = 2; i <= n; i++)
    19         {
    20             scanf("%lld", &p);
    21             sum[i] = sum[i-1] + p;
    22         }
    23         memset(dp, 0, sizeof(dp));
    24         dp[m][1] = sum[m];
    25         for (int j = 1; j <= k; j++)
    26         {
    27             for (int i = m+1; i <= n; i++)
    28             {
    29                 dp[i][j] = max(dp[i-1][j], dp[i-m][j-1]+sum[i]-sum[i-m]);
    30             }
    31         }
    32         printf("%lld
    ", dp[n][k]);
    33     }
    34     return 0;
    35 }
    View Code
  • 相关阅读:
    ACM
    Java实现排序
    HTML导出Excel文件(兼容IE及所有浏览器)
    WebForm应用log4net记录错误日志——使用线程列队写入
    @RefreshScope 配置方法
    Eclipse oxygen 版本汉化教程
    创建Dynamic Web Project时 显示最新Apache Tomcat 8.0 的方法
    微软汉字转拼音
    Ueditor 前后端分离实现文件上传到独立服务器
    汉字转拼音类(多音字)
  • 原文地址:https://www.cnblogs.com/windysai/p/3985252.html
Copyright © 2011-2022 走看看