zoukankan      html  css  js  c++  java
  • 情书

    [LuoGu]P2112 鸿雁传书

    (看到标题的你在想什么?)

    这道题讲了小明给小红写情书的故事.

    题意简化:

    给你(n)个字符串,以及(k),要求把字符串分为(k)行,使得每一行的字母方差最小(不能改变每个字符串的相对位置)

    思路

    这个字符串屁用没得。我们只需要知道字符串的长度就行了,然后这个就变成了一个序列划分的问题。

    要求把原序列分成(k)个子序列,使得这(k)个子序列的方差最小,果断dp。

    方差 ?

    设整个序列平均数为(a),则(a)=(frac{1}{n}) (sum_{i=1}^{i=n}{a_i})((a_i)为原序列第(i)项的权值)

    方差(s^2) =(frac{1}{n}) (sum_{i = 1}^{i = n}{(a_i - a)}^2)

    不妨展开式子:(s^2) = (frac{1}{n}) {(sum_{i=1}^{i=n})(a_i^2) + (n*a^2) - (sum_{i=1}^{i=n})(2 * a * a_i)}

    发现(a)肯定是不会变的.....这个变量就可以简单处理了

    同时关于方差还有一个式子:(s^2) = (sum_{i = 1}^{i = n}{a[i]^2} * n - (sum_{i = 1}^{i = n}{a[i]})^2) (* frac{1}{n^2})

    然后我们就好处理了。

    (DP[i][j])表示前(i)个字符串丢进前(j)行可以获得的最小方差(或许我们也暂时不能称为方差,因为没有除以n)。

    然后我们可以枚举分割点,假设为(k)是分割点。也就是,第(k)个字符串到第(i)个字符串丢进第j行。用一个前缀和比较好维护!求使得方差最小的分割点转移即可。

    于是动态规划方程为:(DP[i][j + 1] = min(DP[i][j + 1] , DP[k][j] + (sum[i] - sum[k]- avg)^2))

    ((sum[i],sum[j])是前缀和,(avg)是整个序列的平均数 ,根据分析这个平均数是不会变的)

    同时我们也没必要每次除以长度,因为这样子显然不好处理,在最后的时候除以一个(m)即可

    同时,说一个偷懒的好技巧,对于这种求平方的东西,我们可以用一个函数来完成,就比如我写的:

    double Double(double x)
    {
    	return x * x;
    }
    

    这样子可以减少代码长度并且可以让你的式子看起来不那么冗长,更加美观!

    Code

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1005;
    int n, m;
    double avg, a[N], sum[N], dp[N][N];
    char str[N];
    double Double(double x)
    {
    	return x * x;
    }
    
    void prepare()
    {
    	for(int i = 1 ; i <= n ; i ++)
        {
            cin >> str;
            sum[i] = sum[i - 1] + strlen(str);//前缀和
        }
        avg = sum[n] / m;
        for(int i = 1 ; i <= n ; i ++)
        	for(int j = 1 ; j <= m ; j ++)
        	 dp[i][j] = 1e8;//初始化
        for(int i = 1 ; i <= n ; i ++)
        	dp[i][1] = Double((sum[i] - avg));//预处理出只放入第一个的情况 
    }
    int main(){
        cin >> n >> m;
        prepare();
       for(int j = 1 ; j <= m ; j ++)
            for(int k = j ; k <= n ; k ++)//分割点
                for(int i = k + 1 ; i <= n ; i ++)//转移
        dp[i][j + 1] = min(dp[i][j + 1], dp[k][j] + Double((sum[i] - sum[k] - avg)));
        printf("%.1lf", dp[n][m] / m);
        return 0;
    }
    
  • 相关阅读:
    Java_Habse_add
    Java_Habse_shell
    android Studio 出现:Unable to resolve dependency for ':app@debug/compileClasspath'
    微信小程序云函数中有以下未安装的依赖,如果未安装即全量上传
    Bittorrent Protocol Specification v1.0 中文
    BT客户端实现 Peer协议设计
    NGINX 配置 SSL 双向认证
    openssl、x509、crt、cer、key、csr、ssl、tls 这些都是什么鬼?
    ssl双向认证和单向认证原理
    网络服务器之HTTPS服务
  • 原文地址:https://www.cnblogs.com/MYCui/p/13898514.html
Copyright © 2011-2022 走看看