POJ 1065 & 3636的区别

  两个题目看起来没什么区别,都是嵌套,唯一的不同就是一个要求l <= l' and w <= w'. 而另一个则要求w1 < w2 and h1 < h2.多了一个等于号。1065在很久以前就被我水过了。搜了一下解题报告都是有关偏序集的。抑或是跟最长上升子序列有关。其实以我自己的想法完全可以模拟accepted掉,当然代价就是时间效率可能没有那么好。最坏情况下是n^2级,在3636大概是花了800ms过了。

  首先是1065,想法很简单,就是先二级排序,如果l相等就对w排序,都是升序排列。然后设置一个标记访问变量。从第一个开始遍历,如果这个位置还没有访问,就在后面没有访问的位置里面找l和w都比当前大的,标记为已访问,更新l和w的最小值。代码更容易看懂:

#include<iostream>
#include<algorithm>
using namespace std;
struct arra{
	int a, b;
};
arra num[5000];
int cmp(const void *a,const void *b)
{
     struct arra *c=(struct arra*)a;
     struct  arra *d=(struct arra*)b;
	 if (c->a == d->a)
		 return c->b - d->b;
     return c->a - d->a;  
}
int
main()
{
	int tot;
	int i, j, k;
	int a;
	int c;
	int mina;
	int minb;
	int vi[5000];
	scanf("%d", &tot);
	for (i = 0; i < tot; i++)
	{
		scanf("%d", &a);
		memset(vi, 0, sizeof(vi));
		c = 0;
		for (j = 0; j < a; j++)
			scanf("%d%d", &num[j].a, &num[j].b);
		qsort(num, a ,sizeof(num[0]), cmp);
		for (j = 0; j < a; j++)
		{
			if (!vi[j])
			{
			    minb = num[j].b;
				c++;
				for (k = j + 1; k < a; k++)
				{
					if (!vi[k] && num[k].b >= minb)
					{
						vi[k] = 1;
						minb = num[k].b;
					}
				}
			}
		}
		printf("%d\n", c);
	}
	return 0;
}

至于3636则有了一点小小的变化,多了一个等于。其实还是可以用原来的方法求,只是需要变两个地方。

首先就是排序上,不能再用原来的方法排序。因为如果w相等的时候是应该先处理h大的,为什呢。设w1==w2,h1<h2。假设先处理小的,如果后面出现了w3>w1,h3>h2时,先嵌入了(w1,h1),再出现w4>w3,h4<=h2时就多出了一个。比如网上出现的一个样例:

5
1 8 2 4 2 3 3 5 4 4


这个例子非常便于理解。所以排序应该改成:

bool cmp(arra a, arra b){
    if (a.a == b.a)
        return a.b > b.b;
    return a.a < b.a;
}

另外还有一个地方就是内层循环时判断条件应该变成:

if (!vi[k] && (num[k].a > mina && num[k].b > minb)){
    vi[k] = 1;
    minb = num[k].b;
    mina = num[k].a;
}

3636代码如下:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

struct arra{
	int a, b;
};

arra num[20005];

bool cmp(arra a, arra b){
    if (a.a == b.a)
        return a.b > b.b;
    return a.a < b.a;
}

int main()
{
	int tot;
	int i, j, k;
	int a;
	int c;
	int mina;
	int minb;
	int vi[20005];
	
	scanf("%d", &tot);

	for (i = 0; i < tot; i++)
	{
		scanf("%d", &a);
		memset(vi, 0, sizeof(vi));
		c = 0;
		
		for (j = 0; j < a; j++)
			scanf("%d%d", &num[j].a, &num[j].b);

		sort(num, num + a , cmp);

		for (j = 0; j < a; j++)
		{
			if (!vi[j])
			{
			    minb = num[j].b;
			    mina = num[j].a;
				c++;
				for (k = j + 1; k < a; k++)
				{
					if (!vi[k] && (num[k].a > mina && num[k].b > minb))
					{
						vi[k] = 1;
						minb = num[k].b;
						mina = num[k].a;
					}
				}
			}
		}
		printf("%d\n", c);
	}
	return 0;
}
posted @ 2011-08-06 20:39  like@neu  阅读(281)  评论(2编辑  收藏  举报