转自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;
}

【转】毛虫算法——尺取法的更多相关文章

  1. 【算法•日更•第二十三期】数据结构:two-pointer(尺取法)&莫队

    ▎引入 ☞『例题』 一道十分easy的题: 洛谷P1638 长度为n的序列,m种数 找一个最短区间,使得所有数出现一遍 n≤1e6 ,m≤2e3. ☞『分析』 这道题非常的简单,但是如果不会two-p ...

  2. HDU 5358 尺取法+枚举

    题意:给一个数列,按如下公式求和. 分析:场上做的时候,傻傻以为是线段树,也没想出题者为啥出log2,就是S(i,j) 的二进制表示的位数.只能说我做题依旧太死板,让求和就按规矩求和,多考虑一下就能发 ...

  3. Codeforces Round #364 (Div.2) C:They Are Everywhere(双指针/尺取法)

    题目链接: http://codeforces.com/contest/701/problem/C 题意: 给出一个长度为n的字符串,要我们找出最小的子字符串包含所有的不同字符. 分析: 1.尺取法, ...

  4. poj3061 Subsequence(尺取法)

    https://vjudge.net/problem/POJ-3061 尺取发,s和t不断推进的算法.因为每一轮s都推进1所以复杂度为O(n) #include<iostream> #in ...

  5. POJ 3061 Subsequence(尺取法)

    Subsequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 18145   Accepted: 7751 Desc ...

  6. POJ 3061 Subsequence ( 尺取法)

    题目链接 Description A sequence of N positive integers (10 < N < 100 000), each of them less than ...

  7. 题解报告:poj 3061 Subsequence(前缀+二分or尺取法)

    Description A sequence of N positive integers (10 < N < 100 000), each of them less than or eq ...

  8. POJ 3061 Subsequence 二分或者尺取法

    http://poj.org/problem?id=3061 题目大意: 给定长度为n的整列整数a[0],a[1],--a[n-1],以及整数S,求出总和不小于S的连续子序列的长度的最小值. 思路: ...

  9. POJ 3061  Subsequence   尺取法   挑战146页

    ---恢复内容开始--- Subsequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10487   Accept ...

随机推荐

  1. [转帖]预警 | Linux 爆“SACK Panic”远程DoS漏洞,大量主机受影响

    预警 | Linux 爆“SACK Panic”远程DoS漏洞,大量主机受影响   https://cloud.tencent.com/developer/article/1447879 所有的 版本 ...

  2. ubuntu 安装 TensorFlow、opencv3 的 tips

    安装tensorflow: 创建tensorflow虚拟环境 conda create -n  tensorflow python=2.7 输入命令查看可用版本的tensorflow-gpu cond ...

  3. Codeforces1256E_Yet Another Division Into Teams

    题意 n个人,每人有一个能力值a[i],要求分成多个队伍,每个队伍至少3个人,使得所有队伍的max(a[i])-min(a[i])之和最小. 分析 不会巧妙的dp,想了一天只想到了暴力的dp. 先排序 ...

  4. 下载MySQL的rpm包安装MySQL

    cd /usr/local/src wget https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-community-server-5.7.27-1.el ...

  5. python模块导入总结

    python模块导入总结 模块导入方式 定义test.py模块 def print_func(): print("hello") import 语句 导入模块语法 import m ...

  6. git和svn 及git使用&解决上线冲突

    一.svn git的工作流程 git 的工作流程图 二.git的基础使用 git 的安装 1.下载对应版本:https://git-scm.com/download 2.安装git:在选取安装路径的下 ...

  7. 工具使用——VMware安装及使用

    一.VMware的安装 本文使用VMware 14 pro,双击打开安装包,点击下一步: 选中我接受许可协议中的条款,点击下一步: 选择安装路径,点击下一步: 点击下一步: 点击下一步: 点击安装: ...

  8. Linux系统性能测试工具(九)——文件系统的读写性能测试工具之iozone

    本文介绍关于Linux系统(适用于centos/ubuntu等)的文件系统的读写性能测试工具-iozone: 参考链接: https://www.cnblogs.com/Dev0ps/p/788938 ...

  9. nodejs 常用插件

    .circular-json npm install circular-json JSON.parse高级版 .cookie-parser .md5-node .multer 上传插件 .npm i ...

  10. zabbix 数据库问题

    Too many connections ::052844.247 Cannot connect to the database. Exiting... :: started [trapper #] ...