您的位置:首页 > 编程语言

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

2012-02-29 11:23 417 查看
#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:
1
1
1
100000
6
1 1 1 1 1 1
5
1 8 8 8 1
6
1 2 3 4 5 6
5
1 2 3 4 4
8
1 2 3 3 3 4 5 6
10
1 2 2 2 4 2 5 2 2 2
18
1 2 3 3 3 3 2 1 1 1 1 2 2 2 2 2 3 3
5
1 2 2 3 1

5
1 2 2 2 1

5
1 2 2 2 2

6
1 2 3 2 3 1

9
1 2 3 4 5 4 3 2 1

10

1 2 7 9 10 7 10 3 2 1

11

1 1 2 6 8 5 6 6 6 6 6
State:
9862066	lyx5398	3320	Accepted	1104K	344MS	C++	1506B	2012-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 INPUT
using 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];  //存储的压缩、编号过得ideas
int 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: