标签:
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