尺取法(图文解析、初学推荐)
文章目录
- 最少连续页(poj3320)
- 分析题意
- 第一步:找第一个满足条件区间
- 第二步:开始将左端边界向右移,达到“缩小”区间、减少连续页的目的。
- 归纳总结代码
尺取法:顾名思义,像尺子一样取一段,借用挑战书上面的话说,尺取法通常是对数组保存一对下标,即所选取的区间的左右端点,然后根据实际情况不断地推进区间左右端点以得出答案。尺取法比直接暴力枚举区间效率高很多,尤其是数据量大的时候,所以说尺取法是一种高效的枚举区间的方法,是一种技巧,一般用于求取有一定限制的区间个数或最短的区间等等。当然任何技巧都存在其不足的地方,有些情况下尺取法不可行,无法得出正确答案,所以要先判断是否可以使用尺取法再进行计算。
本人为一名普通二本学校自动化专业的大二学生,对编程有着少许兴趣。
最近想了解什么是尺取法,于是想写道简单尺取法相关的题目,当练一练手。
最少连续页(poj3320)
题意:一本书有P页,每一页都一个知识点,求去最少的连续页数覆盖所有的知识点。
样例
输入:
6
1 1 3 1 2 3
输出:
3
备注:一本书有6页,第一页知识点为1…第6页知识点为3。
分析题意
按照尺取法的定义:一种高效的枚举区间的方法。我们应该先在找一个满足条件的区间(不一定是最优),然后再通过将左边界向右移、右边界向右移的方式需找最优区间。
第一步:找第一个满足条件区间
为了能够更好地找到最优区间,我们需要先了解有多少个不同的知识点、在已读的页数中每个知识点出现了几次。
map <int, int> cnt;
set <int> t;
//set主要是统计不同的知识点
//set不允许重复插入 每个元素都是不同的
//用map记录每个知识点在连续页中出现的次数
①:可以用set容器“不能重复插入”的特性,统计书中出一共有多少个不同的知识点。
for (int i = 0; i < p; i++){ scanf("%d", &a[i]);t.insert(a[i]);}int num = t.size();
插入个数 num=3
②:可以用map容器“映射”的特性,统计出在已读的页数中相同知识点出现次数。
while (end<p && sum<num){ //选取不同知识点 if (cnt[a[end]] == 0) sum++;cnt[a[end]]++;end++;}
第二步:开始将左端边界向右移,达到“缩小”区间、减少连续页的目的。
begin:左边界下标 end:右边界下标
ans:当前已读最少连续页
在满足条件的区间里
如果右边界下标减去左边界下标小于当前已读最少连续页。
那么右边界下标减去左边界下标就是当前最少页数。
如果end-begin<ans,则ans=end-begin+1。
初始状态(第一个满足条件区间)
当前状态:begin=0 end=4 ans=5
当a[0]知识点在已读页数出现过,则将左边界向右移,右边界不变。
当前状态:begin=1 end=4 ans=4
当a[1]知识点在已读页数出现过,左边界向右移,右边界不变。
当前状态:begin=2 end=4 ans=3
当a[2]知识点在已读页数未出现过,右边界要向右移,找到满足条件的区间。
当前状态:begin=3 end=4 ans=3
当前状态:begin=1 end=5 ans=3
右边界找到合适位置后,左边界再向右移。
此时a[3]知识点在已读页数未出现过,右边界要向右移,找到满足条件的区间。可是右边界已经到达最后一页,结束查找。
最终得到最少页数为3。
while (1){ //begin:左边界 end:右边界 //num不同的知识点 sum已读知识点 while (end<p && sum<num){ //选取不同知识点 if (cnt[a[end]] == 0) sum++;cnt[a[end]]++;end++;} //读完了,退出循环 if (end==p) break;//判断有没有更小的连续页 if(ans>end-begin)ans = end-begin;//ans=end-begin//因为end在上面循环中多加了一个1 //向前推 cnt[a[begin]]--;if(cnt[a[begin]]==0)sum--; begin++;}
归纳总结代码
通俗版
//通俗版
#include <bits/stdc++.h>
#include<algorithm>
#include <set>
#include <map>
#define MAX 1000010
#define ll long long
#define INF 1000010
using namespace std;
int a[MAX];
map <int, int> cnt;
set <int> t;int main()
{int p, ans = INF, begin=0, end=0, sum=0;scanf("%d", &p);for (int i = 0; i < p; i++){ scanf("%d", &a[i]);t.insert(a[i]);}int num = t.size();while (1){ while (end<p && sum<num){ if (cnt[a[end]] == 0) sum++;cnt[a[end]]++;end++;} if (end==p) break;if(ans>end-begin)ans = end-begin;cnt[a[begin]]--;if(cnt[a[begin]]==0)sum--; begin++;}cout<<ans<<endl;return 0;
}
精简版(来源网上)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <set>
#include <map>
#define MAX 1000010
#define LL long long
#define INF 0x3f3f3f3fusing namespace std;
int a[MAX];
map <int, int> cnt;
set <int> t;
int p, ans = INF, st, en, sum;int main()
{scanf("%d", &p);for (int i = 0; i < p; i++) scanf("%d", a+i), t.insert(a[i]);int num = t.size();while (1){while (en<p && sum<num)if (cnt[a[en++]]++ == 0) sum++;if (sum < num) break;ans = min(ans, en-st);if (--cnt[a[st++]] == 0) sum--;}printf("%d\n", ans);return 0;
}
希望能够将自己的一些学习经验分享给有需要的人。
我是小郑,一个坚持不懈的小白。
博客参考链接
尺取法(图文解析、初学推荐)相关推荐
- 尺取法 --算法竞赛专题解析(2)
本系列文章将于2021年整理出版,书名<算法竞赛专题解析>. 前驱教材:<算法竞赛入门到进阶> 清华大学出版社 2019.8 网购:京东 当当 作者签名书 如有建议, ...
- POJ-2566,HDU-1058,POJ-3320,POJ-3061(尺取法)
题目链接: Bound Found 思路 用前缀和先统计每个数到第一个数的总和.因为尺取法需要数组有序,所以对前缀和得到的数组排序.设立两个类似指针了l,r,使得l,r不断前进,并记录这之间产生的最小 ...
- (尺取法模板题) QLU_ACM 2021 专题训练(一) D - Subsequence 题解
D - Subsequence POJ - 3061 <----------- 原题在这 题目大意 给定数组a,求其符合∑a[i] > S 的最短子数列. 尺取法解析 蒟蒻这道题WA了8次 ...
- 二叉查找树(一)之 图文解析 和 C语言的实现
本文转载至http://www.cnblogs.com/skywang12345/p/3576328.html 二叉查找树(一)之 图文解析 和 C语言的实现 概要 本章先对二叉树的相关理论知识进行介 ...
- CF660C Hard Process(尺取法)
整理的算法模板合集: ACM模板 尺取法 题目中要我们求最多改变k次后连续的1的最长长度.那么转换一下,不就是求至多包含k个0的子串的最长长度吗? 直接套用尺取法的思想,维护两端点,一旦0的个数超过k ...
- 【常用技巧精选】尺取法
整理的算法模板合集: ACM模板 目录 1.反向扫描 1 找指定和的整数对 A.UVA1121 Subsequence B.POJ 3320 Jessica's Reading Problem C.l ...
- ACM—各种模拟 总结(字符串,尺取法,数学问题)习题汇总
目录 一.字符串模拟 二. 高精度计算 1. 回文数(高精度,进制转换) 三.数学问题模拟 四.尺取法(双指针法) 1.都说小镇的切糕贵 (尺取法,字符串) umi和弓道 五.奇怪的模拟 x的位数=l ...
- 尺取法 POJ 3601 Subsequence
题目传送门 1 /* 2 题意:求连续子序列的和不小于s的长度的最小值 3 尺取法:对数组保存一组下标(起点,终点),使用两端点得到答案 4 1. 记录前i项的总和,求[i, p)长度的最小值,用二分 ...
- poj2739(尺取法+质数筛)
题意:给你一个数,问这个数能否等于一系列连续的质数的和: 解题思路:质数筛打出质数表:然后就是尺取法解决: 代码: #include<iostream> #include<algor ...
最新文章
- C++ Primer 第三版 读书笔记
- asp.net模糊查询存储过程
- Mint-UI 的 DatetimePicker 日期时间插件的安装与使用
- c int转char数组_C语言 指向数组和字符串的指针
- Jmeter5 语言中文
- Cisco2960交换机密码忘记恢复教程
- vuejs之v-if-ajax异步请求数据遇到的坑
- linux学习笔记:Linux 文件的基本属性
- 制作基于WiFi局域网的自动开门装置2.0(Arduino+微信小程序)
- 元转万元单位换算_excel中如何将元换算成万元 excel 万单位 不要万字
- pygame学习笔记——检测鼠标碰到、点击图片
- Linux 常用命令 一顿操作猛如虎
- android录音声波动画,Android开发:仿微信 录音声波
- 大道至简 知易行难 C# 完成WebSocket demo 用GoEasy实现Hello world
- dell服务器显示器接口在哪里,【Dell S2719H 显示器使用总结】安装|接口|边框|背板_摘要频道_什么值得买...
- Android适配全面总结(一)----屏幕适配
- windows文件读取 xxe_XXE任意文件读取(当xml解析内容有输出时)
- ycy支付宝和余额宝 DeBug
- 计算机课程设计答辩评语,【课程设计教师评语】_课程设计指导教师评语模板...
- 联想SR650服务器清除阵列配置信息
热门文章
- 设计师必备的导航网站
- NLP学习基础入门(上)
- 尚硅谷maven视频教程笔记
- ACME网站证书自动化保姆级教程
- 美通社企业新闻汇总 | 2019.1.10 | 全球最受欢迎商旅城市上海第四,华为发布AI数据中心交换机...
- php tcpdf 没有头部,TCPDF使用总结 - 从头笑到尾的个人空间 - OSCHINA - 中文开源技术交流社区...
- 微信支付:小微商户申请入驻第三步:平台证书序列号解密和敏感词加密
- openEuler虚拟机配置yum源
- java 不生成文件下载_java – 浏览器不生成文件下载对话框
- 烤鱼界头牌半天妖发文致歉,背后暴露了哪些问题?