【转】毛虫算法——尺取法
转自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 ...
随机推荐
- 什么是SQL注入以及mybatis中#{}为什么能防止SQL注入而${}为什么不能防止SQL注入
1.什么是SQL注入 答:SQL注入是通过把SQL命令插入到web表单提交或通过页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL指令. 注入攻击的本质是把用户输入的数据当做代码执行. 举例如: ...
- HDU 3182 ——A Magic Lamp(思维)
Description Kiki likes traveling. One day she finds a magic lamp, unfortunately the genie in the lam ...
- Android引用多媒体
res目录下,创建raw目录(Android会自动识别这个目录),如果自己创建的目录,可能无效底下的mp3格式,mp4格式的文件名必须小写. 引用方式: mediaPlayer = MediaPlay ...
- redis 命令都在这了
DEL key [key ...]删除指定的key(一个或多个) DUMP key导出key的值 EXISTS key [key ...]查询一个key是否存在 EXPIRE key seconds设 ...
- git推送新项目到github
1.首先在github上新建一个裸仓库 得到新仓库地址 2.打开本地要添加项目的目录,右键选择git bash,执行命令 (1)git init (2)git remote add origin ht ...
- PHPStorm运行PHP代码
1.完成php代码后,点击空白处,右上角会出现 chrome.firefox等浏览器的图标,选择一个电脑上已有图标 2.默认情况下浏览器会提示“bad gateway”,此时需要配置phpstorm对 ...
- jmeter的三种参数化方法
JMeter的三种参数化方式包括: 1.用户参数 2.函数助手 3.CSV Data Set Config 一.用户参数 位置:添加-前置处理器-用户参数 操作:可添加多个变量或者参数 二.函数助手 ...
- roll out项目中原系统自定义程序不能编辑
1.SE38编辑时报 程序源系统与现阶段系统不一致:Carry out repairs in non-original systems only if urgent 2.SE16N 查看表TADIR, ...
- Assets.xcassets的详细使用方法
开始之前,首先回顾一下iOS7初体验(1)——第一个应用程序HelloWorld中的一张图,如下所示: 本文分享一下Images.xcassets的体验~_~ 1. 打开此前使用过的HelloWorl ...
- Delphi 帮助的使用