尺取法;应用于有这么一类问题,需要在给的一组数据中找到不大于某一个上限的“最优连续子序列”
先拿poj3061;http://poj.org/problem?id=3061
给长度为n的数组和一个整数m,求总和不小于m的连续子序列的最小长度;
这里就适合用,尺取法;;
先看一下他查找的思路吧’
正如该图,黄色区域就是每次查找的范围,依次可以大概看出尺取法的查找过程;
可以看题目代码了;
#include<stdio.h>
int main()
{
int t,n,s,ans, min, i, l,w,a[100005];
scanf("%d",&t);
while(t--){
scanf("%d %d",&n,&s);
for(i = 0; i < n; i++){
scanf("%d",&a[i]);
}
int l = 0,w= 0,sum = 0,ans=n+1;
while(1){
while(w < n && sum<s){
sum+=a[w];
w++;
}
if(sum < s){
break;
}
min = w-l;
if(min > ans)
min = ans;
ans = min;
sum -= a[l++];
}
if(ans == n+1){
printf("0\n");
}
else{
printf("%d\n",ans);
}
}
}
单独分析一下,那个while循环吧,那里就是尺取法的代码实现;
int l = 0,w= 0,sum = 0,ans=n+1;
while(1){
while(w < n && sum<s){//从前面开始
sum+=a[w];
w++;
}
if(sum < s){//条件不满足了;
break;
}
min = w-l;
if(min > ans)
min = ans;
ans = min;//ans就是最小长度
sum -= a[l++];//尺取法的前进;
}
看第二题;hdu5776
http://acm.hdu.edu.cn/showproblem.php?pid=5776
先看下尺取法代码实现;
int l = 0, sum = 0, w = 0,flag = 0;
while(l < n){
while(w < n && sum < m){//从前面开始
sum += a[w];
w++;
}
if(sum == m){//满足条件
flag = 1;
break;
}
sum -= a[l];//尺取法前进
l++;
}
再看题目代码
#include<stdio.h>
int main()
{
int t, n, m, i, j, l, sum,a[100005];
scanf("%d",&t);
while(t--){
scanf("%d %d",&n, &m);
for(i = 0; i < n; i++){
scanf("%d",&a[i]);
a[i] = a[i]%m;
}
int l = 0, sum = 0, w = 0,flag = 0;
while(l < n){
while(w < n && sum < m){
sum += a[w];
w++;
}
if(sum == m){
flag = 1;
break;
}
sum -= a[l];
l++;
}
if(flag)printf("YES\n");
else printf("NO\n");
}
}
该题还可以用其他方法可以过;
尺取法,还来一题;
poj3320
http://poj.org/problem?id=3320
题解以后补上