题意
就是说一共有p页,每一页有一个知识点(可以重复)。找出一些连续的页数,使得所有的知识点全部覆盖,求最小的连续页数
代码
#include <stdio.h>
#include <set>
#include <map>
using namespace std;
int point[10000005];
int main()
{
int p;
while (scanf("%d",&p)!=EOF)
{
set<int>a;
for (int i=0;i<p;i++)
{
scanf("%d",&point[i]);
a.insert(point[i]);
}
int n=a.size(); //求出总的知识点的数量
int num=0; //num指当前包含的知识点的种类数(最大为n)
int s=0,t=0; //s,t表示要求的连续页数的头指针和尾指针
int res=p; //res表示当前已知的最小连续页数
map<int,int>count; //count表示 个数【知识点】(某个知识点的个数)
while(1)
{
while(t<p&&num<n) //从0开始往后加,保证最后一页肯定比书的页数小。
{
if (count[point[t++]]++==0) //count为零表示出现的新的知识点
num++;
}
if (num<n) break;
res=min(res,t-s);
if (--count[point[s++]]==0) //减去最前面一页看能否有更小的页数出现
num--;
}
printf("%d\n",res);
}
return 0;
}
一开始的目标长度为零,通过while(1)里面的第一个循环不断向后移动尾指针,使得所有的知识点都被包含。当n==num表示完全包含了就退出内层的while循环,到最下面的一个if语句如果减去前面一页(头指针后移)使得某个知识点不被包含了,然后继续看后面能不能有某页可以使得它被包含。并选择更少的那个页数。退出大循环的条件是——当头指针移过某页之后,即使其后的所有页数全部加上也无法包括某个知识点。在此之前一定有某个res是最少的且能包含所有的知识点。