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

来源:互联网 发布:图片源码是什么 编辑:程序博客网 时间:2024/05/21 20:24

算是自己的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))//当右端点到最右侧时,如果缩小范围后发现前左端点对应的颜色在后面没了。说明不用再缩小区间了                {                    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;}

年轻人不要老熬夜~~~

原创粉丝点击