两个题目看起来没什么区别,都是嵌套,唯一的不同就是一个要求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;
}