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

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

4周前 (08-19)

洛谷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)需提前判断,方差计算需注意浮点数精度。


原创内容 转载请注明出处

分享给朋友:

相关文章

力扣198.打家劫舍|动态规划解法中的特殊边界处理

力扣198.打家劫舍|动态规划解法中的特殊边界处理

题意解析:在排列成直线的房屋群中,每个房屋藏有价值不同的财物。小偷不能连续抢劫相邻的两间房屋,否则会触发警报。我们需要设计一套抢劫策略,使得在不触发警报的前提下,能够获取的最大财物总和。这个问题本质上...

【深度优先搜索实战】力扣547题:省份数量问题的图论解法

【深度优先搜索实战】力扣547题:省份数量问题的图论解法

题目解读‌我们面对的是一个典型的图论问题:给定一个城市的连接矩阵,需要计算其中相互连通的城市群(省份)数量。这个问题可以抽象为无向图中的连通分量计算,每个城市代表图中的一个节点,城市之间的连接关系代表...

力扣5:中心扩散法 轻松破解最长回文子串

力扣5:中心扩散法 轻松破解最长回文子串

题目解读:在一个给定的字符串中,我们需要找到最长的回文子串。回文是指正读反读都相同的字符串,如"aba"、"abba"都是回文。这个问题看似简单,但要在字符串中...

IOI 1994 洛谷1216:如何用O(1)空间解决数字三角形问题?附代码实现

IOI 1994 洛谷1216:如何用O(1)空间解决数字三角形问题?附代码实现

题目重解:数字三角形是一个经典的动态规划问题,给定一个由数字组成的三角形结构,从顶部出发,每次可以移动到下方相邻的数字,最终到达底部。我们需要找到一条路径,使得路径上经过的数字总和最大。这个问题可以很...

力扣965题深度解析:单值二叉树的判断技巧

力扣965题深度解析:单值二叉树的判断技巧

重新解读题目 判断一棵二叉树是否为“单值二叉树”,即所有节点的值是否完全相同。题目看似简单,实则考验对树结构递归特性的理解。若一棵树的所有节点值相同,其必然满足:根节点与左右子树的值一致,且...

洛谷2804题解:基于Fenwick树与离散化的区间统计优化方案

洛谷2804题解:基于Fenwick树与离散化的区间统计优化方案

一、题目解读洛谷2804题要求解决一个涉及区间统计的问题,核心在于高效计算满足特定条件的元素数量。题目可能涉及前缀和、区间查询或计数类操作,需处理大范围数据及可能的负数输入。通过代码分析可知,关键需求...

发表评论

访客

看不清,换一张

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