当前位置:首页 > 洛谷 > 洛谷2112题:用动态规划思想解决字符串分割

洛谷2112题:用动态规划思想解决字符串分割

2小时前

洛谷2112题:用动态规划思想解决字符串分割 前缀和 字符串 动态规划 洛谷题解 C++ 第1张

一、题目解读

洛谷P2112题要求将N个字符串分割为K行,使各行字符总数方差最小。输入包含N个字符串及目标行数K,需输出最小方差除以K的数值(保留一位小数)。题目难点在于高效计算分割方案,需平衡时间复杂度与精度要求。

二、解题思路

动态规划(DP)求解。核心思想:将问题拆解为“前i个字符串分成j行的最小方差”,利用前缀和优化累计字符数计算,通过状态转移方程递归求解最优解。关键步骤包括预处理、DP状态定义与转移、方差计算。

三、解题步骤

1. 输入与边界处理:读取N、K及字符串长度,若N=0、K=0或K>N直接输出0。

2. 前缀和预处理:构建prefix数组,存储前i个字符串的总长度,减少重复计算。

3. 动态规划初始化:定义dp[i][j]为前i个字符串分成j行的最小方差,初始化dp[0][0]=0。

4. 状态转移:外层循环i遍历字符串数,内层循环j遍历行数,通过k(分割点)枚举子问题,计算当前行字符总数与平均值的偏差平方,更新dp[i][j]=min(dp[k][j-1]+var)。

5. 输出结果:最终解为dp[N][K],除以K并格式化输出。

四、代码与注释

#include <iostream>
#include <vector>
#include <cmath>
#include <climits>
#include <iomanip>
#include <algorithm>
using namespace std;

const double INF = 1e18; // 定义无穷大,用于初始化DP值

int main() {
    int N, K;
    cin >> N >> K;
    
    // 处理特殊情况
    if (N == 0 || K == 0 || K > N) {
        cout << "0.0" << endl;
        return 0;
    }
    
    vector<int> lens(N); // 存储各字符串长度
    for (int i = 0; i < N; ++i) {
        string s;
        cin >> s;
        lens[i] = s.size();
    }
    
    vector<int> prefix(N+1, 0); // 前缀和数组
    for (int i = 1; i <= N; ++i) {
        prefix[i] = prefix[i-1] + lens[i-1];
    }
    
    // dp[i][j]: 前i个单词分成j行的最小方差和
    vector<vector<double>> dp(N+1, vector<double>(K+1, INF));
    dp[0][0] = 0;
    
    double avg = (double)prefix[N] / K; // 总字符数的平均值
    
    for (int i = 1; i <= N; ++i) {
        for (int j = 1; j <= min(K, i); ++j) {
            for (int k = j-1; k < i; ++k) {
                int sum = prefix[i] - prefix[k]; // 当前行字符总数
                double var = pow(sum - avg, 2); // 方差计算
                dp[i][j] = min(dp[i][j], dp[k][j-1] + var); // 状态转移
            }
        }
    }
    
    cout << fixed << setprecision(1) << dp[N][K]/K << endl; // 输出结果,保留1位小数
    return 0;
}

五、总结

1. 算法核心:动态规划通过子问题最优解推导全局最优,结合前缀和降低时间复杂度。

2. 优化点:状态转移方程的三层循环可通过斜率优化等方法进一步提速,但本题数据范围允许朴素DP。

3. 实际应用:适用于需要平衡分组差异的场景,如资源分配、任务调度等。

4. 注意事项:边界条件(如K>N)需提前判断,方差计算需注意浮点数精度。


原创内容 转载请注明出处

分享给朋友:

相关文章

力扣1137题:动态规划解泰波那契数 高效求解第N项的秘密

力扣1137题:动态规划解泰波那契数 高效求解第N项的秘密

一:重新解读题目泰波那契数列是一个充满数学趣味的递推序列:从第3项开始,每个数均为前三个数的和(即Tₙ₊₃ = Tₙ + Tₙ₊₁ + Tₙ₊₂)。当给定整数n时,需要高效计算出第n项的值。面对此类递...

力扣654:递归分治的艺术 如何用最大元素构建二叉树

力扣654:递归分治的艺术 如何用最大元素构建二叉树

题目重解我们面对一个看似简单却充满递归魅力的题目:给定一个不含重复元素的整数数组,需要构建一棵特殊的二叉树。这个树的每个父节点都必须是当前子数组中的最大元素,而它的左右子树则分别由该最大值左侧和右侧的...

NOIP2005 普及组 洛谷P1408 背包问题的空间优化技巧与实战应用

NOIP2005 普及组 洛谷P1408 背包问题的空间优化技巧与实战应用

题目重解想象你是一名药师,有t分钟在山上采集m种草药。每种草药需要time分钟采集,价值为num。这就像考试时分配时间做题,要选择收益最大的题目组合。题目要求计算在规定时间内能获得的最大草药价值。解题...

CSP-J方格取数题解|动态规划解法|洛谷P7074代码解析

CSP-J方格取数题解|动态规划解法|洛谷P7074代码解析

一、题目解读题目要求在一个n×m的网格中,从左上角到右下角选择一条路径,路径上的数字可重复取用,求取数之和的最大值。路径限制为仅能向右或向下移动。需注意路径的灵活性与重复取数的可能性,传统单向动态规划...

洛谷P4551题解题报告:图论与Trie树优化异或路径问题的实战解析

洛谷P4551题解题报告:图论与Trie树优化异或路径问题的实战解析

一、题目解读洛谷P4551题要求在一个无向图中,寻找任意两点路径权值异或后的最大值。题目输入为图的边信息(点数n和n-1条边),每条边包含起点、终点及权值。需输出所有路径中权值异或的最大值。问题核心在...

1999年NOIP提高组导弹拦截(洛谷P1020)解题思路与动态规划代码解析

1999年NOIP提高组导弹拦截(洛谷P1020)解题思路与动态规划代码解析

一、题目解读    1999年NOIP提高组“导弹拦截”问题(对应洛谷P1020)要求设计导弹拦截系统:给定一组导弹高度数据,需计算最少拦截系统数量,并求最多能...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。