第一次写文章,拿了个简单的题目。
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;
}
说明:在此题中我采用的是升序查找,与题有些相悖,但不要紧。