继续上节;
poj3320;
http://poj.org/problem?id=3320
题目大意;求复习最少的连续页数,但包含所有的知识点;
输入为;有几页,每页包含什么知识点;(1 ≤ P ≤ 1000000);
输出;最少连续的但可以全部复习到的页数;
首先要确定要使用set,map,和尺取法;
set;因为知识都是单一的;满足用set来存储;————set的大小就是知识点的个数;
map;因为每页都对应着一个知识点;存在映射关系;————map对应着每个知识点有多少页了;
尺取法;应用于求最优连续子序列;所以他也当仁不让;————查找最优子序列;
先看代码;
//尺取法加set,map;
#include<stdio.h>
#include<cmath>
#include<algorithm>
#include<map>
#include<set>
using namespace std;
int a[1000005];
int main()
{
set<int> c;
map<int,int> cnt;
int n, i, m;
while(scanf("%d",&n) != EOF){
for(i = 0; i < n; i++){
scanf("%d",&a[i]);
c.insert(a[i]);
}
m = c.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);
}
return 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--;
}
大循环while(1);是为了进行多次查找;
中间的小while是为了进行移动查找;
1,直到找到所有知识点也就是sum=m时,则进行下面的记录最小页数并考虑是否向前移动;
2,或者是直到搜索完毕,r=n并且存在sum