POJ 3320 (尺取法)

博客讨论了如何运用尺取法解决POJ 3320题目,内容涉及寻找覆盖所有知识点的最小连续页数。通过逐步调整页码范围,确保知识点全部覆盖,最终找到最优解。

题意

题目
就是说一共有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是最少的且能包含所有的知识点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值