标签:
Description
Input
Output
Sample Input
4 3 20 30 40 50 30 40 4 20 30 10 10 30 20 40 50 3 10 30 20 20 30 10 4 10 10 20 30 40 50 39 51
Sample Output
1 2 3 2
就是有一堆的长和宽知道的玩偶,小的玩偶可以嵌套在大的里面,只有当长和宽都比它要嵌套在里面的小的时候才可以(长宽不能互换)问多有嵌套完毕后,还有多有个玩偶(最少的)。
解题思路:
要求出最多的能嵌套的个数,如果用贪心思想,势必会TLE,必然要寻求别的方法,因为长或宽相同的不能嵌套,那么如果对长按照从大到小的顺序排列,对于长相等的按照从小到大的顺序排列,那么对宽求单调递增子序列即可。不管什么情况,都可以求得最优解。
一个重要的是要用二分求解最长公共子序列获取最优解,主要是为了优化时间。
代码如下:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <map>
#include <cmath>
#include <string>
#define INF 0x3f3f3f3f
using namespace std;
struct Data
{
int w, h;
}s[20010];
bool cmp(Data A, Data B)
{
if(A.w != B.w)
return A.w > B.w;
else
return A.h < B.h;
}
int main()
{
int t, i, j, sum, n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i = 1; i <= n; i++)
{
scanf("%d%d",&s[i].w,&s[i].h);
}
sort(s + 1, s + n + 1, cmp); // 对长从大到小排序,宽从小到大排序
int b[20010],dp[20010];
memset(b, 0, sizeof(b));
memset(dp, 0, sizeof(dp));
sum = -1;
b[0] = -1;
dp[0] = 0;
int top;
for(i = 1, top = 0; i <= n; i++)//利用二分法对宽求最长公共子序列
{
if(s[i].h >= b[top])
{
b[++top] = s[i].h;//b数组记录最长公共子序列
dp[i] = top;//记录当前点的最长公共子序列的元素个数
}
else
{
int l = 1, r = top;
while(l <= r)//二分
{
int mid = (l + r) / 2;
if(s[i].h >= b[mid])
{
l = mid + 1;
}
else
r = mid - 1;
}
b[l] = s[i].h;
dp[i] = l;
}
if(dp[i] > sum)
sum = dp[i];
}
printf("%d\n",sum);
}
return 0;
}
标签:
原文地址:http://blog.csdn.net/bmamb/article/details/51332350