博客
关于我
ACM解题技巧---(尺取法)+ 题目总结
阅读量:321 次
发布时间:2019-03-04

本文共 2657 字,大约阅读时间需要 8 分钟。

今天学习到了一个非常有趣的思路——“尺取”法。这种方法类似于用尺子来量取物体的长度,通过逐步调整两端点的位置来找到最优解。这种方法在编程中也有广泛的应用,特别是在处理一些需要寻找最大或最小值的问题时。

第一题解析

题目要求给定一个长度为n的01字符串,允许进行m次字符转换(0↔1或1↔0),求最后连续的0或1的最长长度。

解题思路

  • 问题分析

    • 我们需要找到最长的连续0或连续1的长度。
    • 每次转换只能改变一个字符,因此需要合理规划转换次数,以最大化连续字符的长度。
  • 尺取法的应用

    • 假设1:假设我们要找最长的连续0。
    • 计数器:每次遇到0,计数器增加。当计数器超过m时,说明需要进行转换。
    • 调整左边界:将左边界右移一位,如果该位置是0,则计数器减少。
    • 更新答案:每次右边界右移一位,更新当前最长连续0的长度。
    • 处理连续1的情况:重复上述过程,找出最长连续1的长度。
    • 取最大的值:最终答案为最长连续0和1中的较大者。
  • 代码实现

    #include 
    using namespace std;void solve() { int n, m; char s[n]; scanf("%s", s); int ans = 0; // 处理连续0的情况 int l = 0, r = 0, cnt = 0; while (r < n) { if (s[r] == '0') { cnt++; while (cnt > m) { if (s[l] == '0') { cnt--; } l++; } } ans = max(ans, r - l + 1); r++; } // 处理连续1的情况 l = 0, r = 0, cnt = 0; while (r < n) { if (s[r] == '1') { cnt++; while (cnt > m) { if (s[l] == '1') { cnt--; } l++; } } ans = max(ans, r - l + 1); r++; } cout << ans << endl;}int main() { int t; scanf("%d", &t); while (t--) { solve(); } return 0;}

    第二题解析

    题目要求给定一个n行m列的矩阵,求一个字矩阵,使得这个矩阵的面积最小,且空座位的个数不少于k。

    解题思路

  • 问题分析

    • 需要找到一个矩阵,使得面积最小,且空座位数至少为k。
    • 这可以转换为一个二维寻找问题,通过枚举行和列来确定矩阵的范围。
  • 尺取法的应用

    • 转换问题:将二维问题转换为一维问题,通过枚举行和列,计算空座位数。
    • 枚举行和列:分别枚举行和列,计算每个可能的矩阵范围,找到最小的面积。
    • 动态调整:使用尺取法动态调整矩阵的范围,确保空座位数满足条件。
  • 代码实现

    #include 
    #include
    using namespace std;int getsum(int x1, int y1, int x2, int y2) { return sa[x2][y2] - sa[x2][y1-1] - sa[x1-1][y2] + sa[x1-1][y1-1];}void solve() { int n, m, k; char mp[n+1][m+1]; for (int i = 1; i <= n; ++i) { scanf("%s", mp[i]+1); for (int j = 1; j <= m; ++j) { if (mp[i][j] == '.') { sa[i][j] = sa[i-1][j] + sa[i][j-1] - sa[i-1][j-1]; } else { sa[i][j] = sa[i-1][j] + sa[i][j-1] - sa[i-1][j-1]; } } } int ans = 0x3f3f3f3f; for (int i = 1; i <= n; ++i) { for (int j = i; j <= n; ++j) { int cc = 1; for (int kk = 1; kk <= m; ++kk) { while (cc <= kk && getsum(i, cc, j, kk) >= k) { ans = min(ans, (j - i + 1) * (kk - cc + 1)); cc++; } } } } cout << ans << endl;}int main() { while (true) { read(n, m, k); if (n == 0 && m == 0 && k == 0) break; solve(); } return 0;}

    总结

    通过上述分析和代码实现,我们可以清晰地看到如何利用尺取法解决不同类型的编程问题。这种方法的核心在于通过动态调整两端点,逐步缩小范围,从而找到最优解。

    转载地址:http://exaq.baihongyu.com/

    你可能感兴趣的文章
    Openlayers map三要素(view,target,layers),及其他参数属性方法介绍
    查看>>
    Openlayers Map事件基础及重点内容讲解
    查看>>
    Openlayers Select的用法、属性、方法、事件介绍
    查看>>
    Openlayers Source基础及重点内容讲解
    查看>>
    Openlayers view三要素(zoom,center,projection)及其他参数属性方法介绍
    查看>>
    OpenLayers 入门使用
    查看>>
    Openlayers 入门教程(一):应该如何学习 Openlayers
    查看>>
    openlayers 入门教程(七):Interactions 篇
    查看>>
    openlayers 入门教程(三):view 篇
    查看>>
    openlayers 入门教程(九):overlay 篇
    查看>>
    openlayers 入门教程(二):map 篇
    查看>>
    openlayers 入门教程(五):sources 篇
    查看>>
    openlayers 入门教程(八):Geoms 篇
    查看>>
    openlayers 入门教程(十三):动画
    查看>>
    openlayers 入门教程(十二):定位与轨迹
    查看>>
    openlayers 入门教程(十五):与 canvas、echart,turf 等交互
    查看>>
    openlayers 入门教程(十四):第三方插件
    查看>>
    openlayers 入门教程(四):layers 篇
    查看>>
    OpenLayers 项目分析(三)-OpenLayers中定制JavaScript内置类
    查看>>
    Openlayers下载与加载geoserver的wms服务显示地图
    查看>>