NOIP 2001 提高组算法题解

作者: | 更新日期:

涉及枚举二分、动态规划、单源最短路等算法

本文首发于公众号:天空的代码世界,微信号:tiankonguse

零、背景

今天继续分享 2001 年 NOIP 提高组题解。

一、一元三次方程求解

题意:给一个一元三次方程的系数,已知方程在 [-100,100] 数据范围内存在三个实数根,且任意两个根之间差的绝对值大于 1,求三个根,精确到小数点2位。

思路:枚举二分

由于题目要求精确到小数点2位,最简单的就是枚举 [-100.00, 100.00],步长为 0.01。
对于每个枚举的点 p,判断 [p,p+1) 之间是否有答案。
如果 p 是答案,则直接枚举下一个。
如果 f(p) * f(p+1) < 0,则在其之间必然有答案。
否则肯定没有答案。

vector<double> ans;
for (double i = -100.00; i <= 100.00; i += 0.01) {
  double l = i, r = l + 1;
  double lv = f(l), rv = f(r);
  if (IsZero(lv)) {
    ans.push_back(l);
    continue;
  }
  if (lv * rv < 0) {
    // 二分法求根
    while (r - l > eps) {
      double mid = (l + r) / 2;
      if (f(l) * f(mid) < 0) {
        r = mid;
      } else {
        l = mid;
      }
    }
    ans.push_back(l);
    i = l;
  }
}

注意事项:如果直接枚举 [-100,100] 且步长为 1,则在整数答案上可能得到重复的答案。
解决方法:对于右端点,单独判断一次是不是答案,是了,直接跳到下一个步长。

vector<double> ans;
for (double i = -102; i < 102; i += 1) {
  double l = i, r = l + 1;
  double lv = f(l), rv = f(r);
  if (IsZero(lv)) {
    ans.push_back(l);
    continue;
  }
  // bad case: rv 是答案,二分会无限趋近于 rv,从而导致答案重复
  if (IsZero(rv)) {
    continue;
  }
  if (lv * rv < 0) {
    // 二分法求根
  }
}

二、数的划分

题意:对整数n 划分为 k 分,求划分数。
规则:相同数字之间没有区别,例如1,1,21,2,1为相同的划分。

思路:动态规划

分析:对于组合类的划分,需要定义当前可以选择的最值。

状态定义:dp[n][k][minVal] 将 n 划分 k 个数字,可以选择的最小数字为 minVal 的方案数。

状态转移方程,范围选择与不选择即可。

dp[n][k][minVal] = dp(n-minVal, k-1, minVal) + dp(n, k, minVal + 1);

复杂度:O(n^2 * k)

三、统计单词个数

题意:给一个字符串和若干单词,问如何将字符串拆分为 k 个字符串,使得每份中包含的单词个数加起来总数最大。
包含规则:单词可以部分重叠,当选用一个单词之后,其第一个字母不能再用。

思路:双重动态规划

第一重:拆分字符串
状态定义:dp(n,k) 前 n 个字符拆分为 k 个字符串的最大值。
状态转移方程:枚举拆分的最后一个字符串,求累计最大值。

dp(n,k) = max(dp(i, k-1) + Count(i+1, n));

第二重:求一个字符串包含的单词个数。
状态定义:Count(l,r) 字符串s[l,r]包含的单词个数。

状态转移方程:

Count(l,r) = Check(l,r) + Count(l+1, r);

Check(l,r) 含义,包含第一个字母时,是否包含某个单词。

四、Car 的旅行路线

题意:每个城市有四个机场,同一个城市内有高铁互通机场,不同城市的机场之间都有航线。
告诉你每个城市高铁的历程单价,以及飞机的历程单价,问从一个城市任意机场到另外一个城市任意机场的最低费用。

思路:单源最短路

每个机场当做一个点,就是4个起点以及4个终点的最短路问题。
多个起点与多个终点比较麻烦,可以通过增加超源点与超汇点,变更1个起点1个终点。

然后直接跑 Dijkstra 即可。

五、最后

这次比赛的四道题都不难。
第一题,枚举二分。
第二题,划分动态规划。
第三题,区间动态规划。
第四题,单源最短路。

《完》

-EOF-

本文公众号:天空的代码世界
个人微信号:tiankonguse
公众号 ID:tiankonguse-code

本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。

关注公众号,接收最新消息

tiankonguse +
穿越