【转】毛虫算法——尺取法
转自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 ...
随机推荐
- CentOS7之ssh-Xshell密钥认证登陆
操作系统版本:CentOS Linux release 7.2.1511 (Core) SSH版本:OpenSSH_6.6.1p1, OpenSSL 1.0.1e-fips 1.打开Xshell工 ...
- OLT设置vlan透传及ONU端口划vlan
CZ-PX-ShangShi-FTTH-OLT-A#show runn System current configuration:!Software Version ISCOM5800E-SMCB_1 ...
- APT高持续渗透攻击-后门篇
APT是指高级持续性威胁, 利用先进的攻击手段对特定目标进行长期持续性网络攻击的攻击形式,APT攻击的原理相对于其他攻击形式更为高级和先进,其高级性主要体现在APT在发动攻击之前需要对攻击对象的业务流 ...
- limux密钥对配置登陆主机
1. Linux主机免密码使用密钥登陆 这里假设主机A(192.168.0.113)用来远程连接主机B(192.168.0.186) 在主机A上执行如下命令来生成配对密钥:ssh-keygen -t ...
- c#获取网络时间
public static DateTime GetInternetDate() { var client = new TcpClient("time.n ...
- jquery判断 input type="file"上传文件是否为空
要想获取type="file"的input内容,用var file = $("id").val();肯定是不行的,下面是代码: html上传按钮为: <i ...
- how to create a flask server
1. use database 2. use redis 3. inport/export excel2007 version+ from flask import send_from_directo ...
- java.lang.IllegalArgumentException: id to load is required for loading
java.lang.IllegalArgumentException: id to load is required for loading at org.hibernate.event.LoadEv ...
- vue单页应用中根据不同城市不同业务添加百度统计代码
问题描述: 我们知道一般的百度统计代码是添加在html的head里的:但是,因为目前项目是用vue开发的单页应用,所以在路由跳转之间不会刷新页面, 统计代码如果放在项目里的index.heml的hea ...
- 雪花算法生成ID
前言我们的数据库在设计时一般有两个ID,自增的id为主键,还有一个业务ID使用UUID生成.自增id在需要分表的情况下做为业务主键不太理想,所以我们增加了uuid作为业务ID,有了业务id仍然还存在自 ...