【转】毛虫算法——尺取法
转自http://www.myexception.cn/program/1839999.html
妹子满分~~~~
毛毛虫算法——尺取法
有这么一类问题,需要在给的一组数据中找到不大于某一个上限的“最优连续子序列”
于是就有了这样一种方法,找这个子序列的过程很像毛毛虫爬行方式,我管它叫毛毛虫算法,比较流行的叫法是“尺取法”。
喏,就像图里的妹纸一样~
还是举个栗子:
Poj3061
给长度为n的数组和一个整数m,求总和不小于m的连续子序列的最小长度
输入
n = 10,m = 15
5 1 3 5 10 7 4 9 2 8
输出
2
那么我们先用sum存当前这个子序列的和,从左边第一个数来存,直到这个子序列的和大于等于m为止,再记录下当前长度。
其实相当于当不满足条件就入队,然后得到队列长度,再将队首元素出队,再进行下一次的入队,直到满足条件再次出队,并且将这一次的长度与历史最短长度进行取舍,最后扫到最后的元素却无法再满足入队条件的时候就结束,此时用O(n)的时间就可以得到答案。
如下,我把样例用毛毛虫爬一遍,下划线的是当前“毛毛虫着地”也就是刚好满足题意的子序列的地方:
5 1 3 5 10 7 4 9 2 8
5 1 3 5 10 7 4 9 2 8
5 1 3 5 10 7 4 9 2 8
5 1 3 5 10 7 4 9 2 8
5 1 3 5 10 7 4 9 2 8
5 1 3 5 10 7 4 9 2 8
5 1 3 5 10 7 4 9 2 8
5 1 3 5 10 7 4 9 2 8
5 1 3 5 10 7 4 9 2 8
祖传代码。。。
C++
/*************************************************************************
> File Name: main.cpp
> Author: haoran
> Created Time: 2015年01月19日 星期一 21时04分36秒
************************************************************************/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <fstream>
#include <algorithm>
using namespace std;
int a[200000];
int main()
{
// freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
cin.tie(false);
int n,max,sum,T; while(cin>>T)
{
while(T--)
{
cin>>n>>max;
for(int i = 0 ; i < n ; i++)
cin>>a[i];
int i = 0,j = 0,sum = 0,ans = n+1;
while(1)
{
while(j < n && sum <= max)
sum += a[j++]; if(sum < max) break;
ans = min(j-i,ans);
sum -= a[i++];
}
if(ans > n)
ans = 0;
printf("%d\n",ans);
}
}
return 0;
}
java大法的
import java.util.Scanner;
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner cin = new Scanner(System.in);
int a[] = new int[100010];
int T = cin.nextInt();
for(int ii = 0 ; ii < T ; ii++)
{
int n = cin.nextInt();
int m = cin.nextInt();
for(int i = 0 ; i < n ; i++)
a[i] = cin.nextInt();
int l = 0,r = 0,ans = m+1,sum = 0;
while(true)
{
while(r < n && sum < m)
sum += a[r++];
if(sum < m)
break;
ans = min(ans,r-l);
sum -= a[l++];
}
if(ans > n)
ans = 0;
System.out.println(ans);
}
}
private static int min(int ans, int sum) {
// TODO Auto-generated method stub
return ans < sum ? ans : sum;
}
}
买一送一,再给大家一颗栗子;
Poj3320
这道题费点脑子,大意:
一个考前一天看一整本书发呆的学渣,找学霸划知识点,学霸告诉他每一页的知识点(每一页只有一个知识点而且页与页之间可以重复知识点!),每一个知识点都用一个数字表示,给你这本书一共有n页厚,学渣很懒,只想读连续若干页的书,还不想看太多页,所以要你帮他找覆盖所有出现过的知识点的连续页的页数最薄有几页。
输入
n = 5
1 8 8 8 1
输出
2
很显然一共有5页书,却只有2个知识点,想读就读前两页,所以就输出2页。先想想需要解决什么问题:
1.要解决出现一共多少个知识点
2.根据当前子序列包含的知识点数来入队、出队
其实就这样。
第一个问题其实可以用set来解决,知识点数量就是set的size大小。
下一个问题其实可以用map来存,存每一页出现的知识点在这个子序列中出现的次数,如果是0的话就把这个知识点放进来并++,直到所有知识点覆盖为止。
在所有知识点覆盖的基础上出队,直到某一个知识点在子序列的出现次数为0的时候,再从后面入队,并在这些操作中记录下最少页数就可以了,剩下的和第一颗栗子一个味道。
祖传C++代码如下~
#include <iostream>
#include <map>
#include <set>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
using namespace std;
int n,m,a[1000010];
void solve()
{
set<int> all ;
map<int,int>cnt;
for(int i = 0 ; i < n ; i++)
{
scanf("%d",&a[i]);
all.insert(a[i]);
} m = all.size();
int l = 0 , r = 0 , ans = n+1,sum = 0;
while(1)
{
while(r < n && sum < m)
if(cnt[ a[r++] ]++ == 0)
sum++;
if(sum < m)break;
ans = min(ans,r-l);
if(--cnt[ a[l++] ] == 0)
sum--;
}
printf("%d\n",ans);
}
int main()
{
#ifdef H_R
freopen("in.txt","r",stdin);
#endif // H_R while(scanf("%d",&n)!=EOF)
{
solve();
}
return 0;
}
【转】毛虫算法——尺取法的更多相关文章
- 【算法•日更•第二十三期】数据结构:two-pointer(尺取法)&莫队
▎引入 ☞『例题』 一道十分easy的题: 洛谷P1638 长度为n的序列,m种数 找一个最短区间,使得所有数出现一遍 n≤1e6 ,m≤2e3. ☞『分析』 这道题非常的简单,但是如果不会two-p ...
- HDU 5358 尺取法+枚举
题意:给一个数列,按如下公式求和. 分析:场上做的时候,傻傻以为是线段树,也没想出题者为啥出log2,就是S(i,j) 的二进制表示的位数.只能说我做题依旧太死板,让求和就按规矩求和,多考虑一下就能发 ...
- Codeforces Round #364 (Div.2) C:They Are Everywhere(双指针/尺取法)
题目链接: http://codeforces.com/contest/701/problem/C 题意: 给出一个长度为n的字符串,要我们找出最小的子字符串包含所有的不同字符. 分析: 1.尺取法, ...
- poj3061 Subsequence(尺取法)
https://vjudge.net/problem/POJ-3061 尺取发,s和t不断推进的算法.因为每一轮s都推进1所以复杂度为O(n) #include<iostream> #in ...
- POJ 3061 Subsequence(尺取法)
Subsequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 18145 Accepted: 7751 Desc ...
- POJ 3061 Subsequence ( 尺取法)
题目链接 Description A sequence of N positive integers (10 < N < 100 000), each of them less than ...
- 题解报告:poj 3061 Subsequence(前缀+二分or尺取法)
Description A sequence of N positive integers (10 < N < 100 000), each of them less than or eq ...
- POJ 3061 Subsequence 二分或者尺取法
http://poj.org/problem?id=3061 题目大意: 给定长度为n的整列整数a[0],a[1],--a[n-1],以及整数S,求出总和不小于S的连续子序列的长度的最小值. 思路: ...
- POJ 3061 Subsequence 尺取法 挑战146页
---恢复内容开始--- Subsequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10487 Accept ...
随机推荐
- PostgreSQL通过解析日志,获取数据库增量变化,pg_recvlogical
1.首先用该工具来看我们的日志变化,需要先将test_decoding插件编译并安装(进入contrib,编译安装即可) 创建一个slot: SELECT * FROM pg_create_logic ...
- numpy将数组保存为文件
保存单个数组 np.save和np.load是读写磁盘数组数据的两个主要函数.默认情况下,数组是以未压缩的原始二进制格式保存在扩展名为.npy的文件中的: 如果文件路径末尾没有扩展名.npy,则该扩展 ...
- PythonDay16
第十六章模块 今日内容 自定义模块 time模块 datetime模块 rendom模块 自定义模块 # import 模块 例:import time# 导入的是time模块中所有的内容(变量,函数 ...
- 洛谷 - P3225 - 矿场搭建 - 双连通分量
https://www.luogu.org/problem/P3225 这个东西有点绕. 最平凡的情况,整个原图只有一个点,那么它坍塌了之后就没有点了,不需要进行任何逃生.否则,当一个点坍塌之后,每个 ...
- Java Web开发技术教程入门-初识动态网页
这段时间学校搞了一个"阅战阅勇"的阅读活动,奖品还是挺丰富的~于是,奔着这些奖品,我去图书馆借了这本<Java Web开发技术教程>.一是为了那些丰富的奖品,二是为了回 ...
- 使用python的kazoo模块连接zookeeper实现最基本的增删改查
kazoo的官方文档地址:https://kazoo.readthedocs.io/en/latest/index.html #!/usr/bin/env python # -*- coding: u ...
- npm学习(八)之如何使用语义化版本
npm的语义化版本控制——Semantic versioning 在新发布的代码中传达更改的程度非常重要,因为有时更新会破坏包需要的代码(称为依赖项).语义化版本控制(semver)是一个旨在解决这个 ...
- docker数据卷挂载
docker数据卷挂载笔记 我们的服务运行时必不可少的会产生一些日志,或是我们需要把容器内的数据进行备份,甚至多个容器之间进行数据共享,这必然涉及容器的数据管理操作. 容器中管理数据主要有两种方式: ...
- springboot项目抓数据后优化配置及四个补充
昨天搞了一个抓取某某平台信息的抓取功能,其中有一个地址url,昨天是写死的,之前也进行配置过,印象有些模糊,今天想配置一下,在properties文件中,由此引发了下面的一系列总结操作: 1.原始模式 ...
- 生产服务器上安装Python
2018-05-17 生产环境的服务器(以下简称内网服务器)由于安全限制,可能无法连接外网.这种情况下将无法直接使用pip命令安装python的包 一.更改pip源 - 默认pip是使用Python官 ...