【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;}