【poj3320】Jessica's reading problem,解题报告+数据+代码

来源:互联网 发布:基本的医学常识知乎 编辑:程序博客网 时间:2024/04/30 13:10
#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#include <climits>#include <map>#include <iostream>/*    Problem : POJ3320-Jessica's reading problem;    Begin Time: 27/2/2012 5:30 p.m.    End Time:   29/2/2012 11:13 a.m    Last Time: 2Days+    Test Data:11110000061 1 1 1 1 151 8 8 8 161 2 3 4 5 651 2 3 4 481 2 3 3 3 4 5 6101 2 2 2 4 2 5 2 2 2181 2 3 3 3 3 2 1 1 1 1 2 2 2 2 2 3 351 2 2 3 151 2 2 2 151 2 2 2 261 2 3 2 3 191 2 3 4 5 4 3 2 1101 2 7 9 10 7 10 3 2 1111 1 2 6 8 5 6 6 6 6 6    State:9862066lyx53983320Accepted1104K344MSC++1506B2012-02-29 10:46:48    思路:    感谢    http://hi.baidu.com/rain_bow_joy/blog/item/bf3e3acbda80c88cc9176811.html    这份解题报告!    把ideas按照出现的顺序编号,比如    1 8 3 3 3 3 5 1    那么1的编号就是1,8的编号就是2,3的编号就是3,5的编号就是4    以下所称的“idea个数”均指编号后的idea的个数,比如上例中    idea个数 = 4    编号存放在nums_id里    然后从第一个元素开始搜索    搜索时,判断当前元素是否在搜索的这个子序列(从0到i)未出现过    如果是,那么该编号(nums_id[i])的元素的最右点的值为当前的i            并且现在已找到的idea个数++,如果与总的idea个数相等            那么取出目前找到的所有idea的最右点的值中最小的。            木桶原理,记得么,亲,只有最左边的值被算在里面            我们才能保证这个区间覆盖了所有元素。            len = i - *tmp + 1;            然后我们把最左边的元素丢弃,*tmp = 0;num--,继续寻找    如果否,那么仅仅刷新该编号的p[nums_id[i]) = i;就可以了    核心算法伪代码如下:    for(int i = 0  ; i <=n; i++)    if(p[nums_id[i]]==0)        p[nums_id[i]] = i;        now_num++;        if(now_num == total)            计算当前区间的最短长度            int* tmp = min_element(p[1],p[total+1]);        if(len < min) min = len;        *tmp = 0;now_num--;    else        p[nums_id[i]] = i;    至于这道题的意思    就是在[0,n]这个区间内找一个最短的区间,使得这个最短区间包含[0,n]的所有    idea,所以我们只要找到[0,n]中所有 包含所有idea 的区间,然后取其长度最短的    就可以了*///#define INPUTusing namespace std;const int MAX_SIZE  = 1100000;int total; //出现的元素总数int lmin = INT_MAX/2; //区间最小长度int p[MAX_SIZE];//每个idea到达的最大点//int num_id[MAX_SIZE]; //每个idea经过压缩后的编号int nums[MAX_SIZE];  //存储的压缩、编号过得ideasint main(int argc,char* argv[]){    int n;    int j;#ifdef INPUT    freopen("b:\\acm\\poj3320\\input.txt","r",stdin);#endif    map<int,int> num_id;    scanf("%d",&n);    for(int i = 1 ; i <= n ; i ++)    {        scanf("%d",&j);        if(num_id[j] == 0)        {            total++;            num_id[j] = total; ///离散化必须用map,不知道为甚。。。        }        nums[i] = num_id[j];    }/**********SOLVE THE PROBLEM ******///////nums的数据大小(比如说可能有数字大于MAX_SIZE)可能出错,需要注意///    int now_num = 0; ///当前搜索到的idea个数(不包括重复的)    int len = 0; ///当前计算的区间长度    int *tmp; ///指向区间左端点的指针    for(int i = 1 ; i <= n ; i++)    {        if( p[nums[i]] == 0)        {            now_num++;            p[nums[i]] = i;            if( now_num == total)            {                tmp = min_element(&p[1],&p[total+1]);                len = i - *tmp + 1;                if( len < lmin)                    lmin = len;                now_num--;                *tmp = 0;            }        }        else        {            p[nums[i]] = i;        }    }    printf("%d\n",lmin);    return 0;}


原创粉丝点击