(HNU_ACM)Sequence

第一次写文章,拿了个简单的题目。

Problem description

Giving a collection S of points on two dimension plane. (S = {(x0,y0), (x1,y1), ... }) We define a point is greater than another point when all its coordinate on two axis are both greater than or equel to another one. Namely, p is greater than q when xp ≥ xq and yp ≥ yq. A sequence is a list points < p1, p2, ... > satisfy that i < j => pi is greater than pj. You can use the elements in S to construct sequences, how many sequences needed to cover a S at least?


 
Input

The input consists of several test cases. Each test case start with a line containing a number n(0 < n ≤ 1000000), the number of points in S. Then n lines follows, each line containing two number, xi, yi(0 ≤ xi, yi ≤ 100000), the position of point i. The input end with EOF.

 
Output

You have to print minium number of sequences needed to cover S in a single line for each case.

 
Sample Input
4
1 1
2 2
3 3
4 4

4
1 5
2 6
2 3
3 4
 
Sample Output
1
2


/********************************************************************************************************************

此题大意是:给一个集合S={(x0, y0), (x1, y1)...........(xn, yn)},集合中的元素s1>s2的条件是:x0>=x1 && y0>=y1。

要求在S中找一些降序子序列,使得这些子序列的元素能够全部覆盖S中的元素,且这些子序列个数最少。

2007-10-4

From acm.hun.cn

*********************************************************************************************************************/

/********************************************************************************************************************
解题方法:

采用贪心算法。

首先将S按X排序,后按Y进行二级排序(排序按升或降都无所谓)。

假设第一个降序子序列A1初始化为{<y0,y0>},A1可以利用原来的S;

再依次从第二个元素开始,对于每一个元素,修改第一个能够被修改的子序列(即S中的yi小于An中的yn),否则另起一子序列Aj。

这样的原理就是利用贪心,留下潜力最大的,修改潜力最小的。

具体看程序。
*********************************************************************************************************************/


程序如下:

#include<stdio.h>
#include<stdlib.h>

#define Max 1000010
typedef struct
{
 long a;
 long b;
}vri;
vri p[Max];

//题中的S

//快排中的比较函数

int cmp(const vri * x, const vri * y)
{
 if(x->a > y->a) return 1;
 if(x->a < y->a) return -1;
 return x->b >= y->b ? 1:-1;
 return 0;
}
int main()
{
 long i, j, k, num;
 while(1)
 {
  if(scanf("%ld", &num) == EOF) break;
  for(i = 0; i < num; i++)
   scanf("%ld %ld", &p[i].a, &p[i].b);
  qsort(p, num, sizeof(p[0]), cmp);                        //qsort
  p[0].a = p[0].b;                                         //第一个子序列
  for(j = 1,i = 1; i < num; i++)                           //j赋为1,表示已经有一个子序列,a用来保存子序列的最后一项        
  {
   for(k = 0; k < j; k++)                                 //在前面的子序列中找可以修改
    if(p[i].b >= p[k].a)                                  //p[i].b  >= 子序列中的最后一项就可以修改
    {
     p[k].a = p[i].b;                                     //保存最后一个修改的
     break;
    }
   if(k >= j) p[j++].a = p[i].b;                         //如果在前面找不到可以修改的,则另起一列
  }
  printf("%ld/n", j);                                    //最后j即为子序列数
 }
 return 0;
}


说明:在此题中我采用的是升序查找,与题有些相悖,但不要紧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值