您的位置:首页 > 其它

HOJ P-2244 Get the Colors(模拟+贪心)

2017-12-01 02:03 253 查看
算是自己的maid blog吧,毕竟对文字没有感觉的我文章写得乱七八糟的

在上次讲链表快排的时候就像发一篇文章了,一直拖到现在要挂科的时候才想起学长当年的话hhh,所以这次在学长的

鼓励下还是发一篇吧(毕竟老吸csdn,不回报回报怎么可以呢)

先整理贪心吧,毕竟学的最早。选这道题,一是因为当时卡的时间最久,首先因为没剪枝tle,然后没有考虑到爆int的

情况疯狂wa。。。哎自己对细节的处理咋就那么弱呢。。。二是因为网上没有题解(你猜我是怎么知道的),如果能

对其他可爱的小伙伴有所帮助的话,不幸荣幸啦。

Problem Description

This problem arises from a research on the newest Web Data Search & Mining technology.

There are several points on the x-axis, each with a color and a unique x-coordinate.



Your task is to calculate the minumum interval on the x-axis that contains all the colors.

Time limit : 3 s Memory limit : 32 mb

Input

This problem has multiple test cases. Each test case begins with an integer N that specifies the number of points. N lines follow, each with two integers Xi and Ci, specifying point i’s x-coordinate and color. 1 ≤ N ≤ 10000, 1 ≤ Ci ≤ 1000. Xi will fit in signed 32-bit integer.

Output

For each test case, output a single integer, which is the length of the minimum interval that contains all the colors.

Sample Input

6

-5 3

-3 1

0 2

1 3

5 2

10 1

Sample Output

4

ac代码:

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
//题意比较好理解,此代码选用暴力找区间的方法,结合一些剪枝的小技巧,注意特殊情况特殊处理

struct node
{
long long x;//32-(-32)会爆int
int cl;
} p[10010];
//对x进行排序

int cmp(const void *a,const void *b)
{
return ((struct node *)a)->x>((struct node *)b)->x;
}

//判断此时是否所有颜色都出现了至少一次
int judge(int arr[],int index)
{
int i;
for(i=1; i<=index; i++)
{
if(arr[i]==0)
{
return 0;//若有的颜色没有去到,则返回0
}
}
return 1;
}

int main()
{
int n,i,j,k,m;
while(scanf("%d",&n)==1)
{
int max=0;
int arr[1010];//在遍历的过程中保存颜色出现的次数
memset(arr+1,-1,sizeof(arr));//这个数组的角标对应点的颜色的编号,用来记录这个颜色是否出现过,初始化为-1
for(i=0; i<n; i++)
{
scanf("%lld%d",&p[i].x,&p[i].cl);
if(p[i].cl>max)
{
max=p[i].cl;//保存颜色编号的最大值
}
if(arr[p[i].cl]==-1)
{
arr[p[i].cl]++;//让出现过的颜色编号初始为0
}
}
long long len=0;
if(n==1)//一个点的时候
{
printf("0\n");
continue;
}
else
{
qsort(p,n,sizeof(p[0]),cmp);
int right=0;//区间右端点
i=0;//区间左端点
for(j=right; j<n; j++)
{
arr[p[j].cl]++;//让每次出现的颜色加一
if(judge(arr,max)==0)//若还有颜色没出现过,则右端点继续右移
{
continue;
}
else//此时说明所有颜色都出现过了
{
len=p[j].x-p[i].x;//len保存答案,此时找到一个可以包含所有颜色的区间
right=j;//让右断点变为现在遍历的地方
break;
}
}
int co=0;
for(i=1; i<n; i++)//以下找最小区间,每次循环左端点右移
{
if(co==1)
{
break;
}
arr[p[i-1].cl]--;//前一个左端点对应颜色-1
if((right==n-1)&&(arr[p[i-1].cl]==0))//当右端点到最右侧时,如果
4000
缩小范围后发现前左端点对应的颜色在后面没了。说明不用再缩小区间了
{
break;
}
else if(arr[p[i-1].cl]>0)//说明此时区间内仍成立,则保存新的区间长度,然后返回左端点继续右移
{
if((p[right].x-p[i].x)<len)
{
len=p[right].x-p[i].x;
}
continue;
}
else//此时右端点没有到最右侧,左端点向右移动后发现颜色不够了,右端点该向右移动了
{
for(j=right+1; j<n; j++)//右端点开始右移
{
arr[p[j].cl]++;
if((j==n-1)&&(arr[p[i-1].cl]==0))//此时说明右端点已经到最右端了,但是区间内仍然有没有出现过的颜色,这个时候左端点就不用向右移动了
{
right=j;
co=1;
break;
}
if(arr[p[i-1].cl]==0)//如果前左端点还是0,则继续右移
{
right=j;
continue;
}
else//说明右端点右移后此时区间又满足题意
{
right=j;
if((p[right].x-p[i].x)<len)
{
len=p[right].x-p[i].x;
}
break;
}
}
}
}
printf("%lld\n",len);
}
}
return 0;
}


年轻人不要老熬夜~~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  题解 原创