原题: http://poj.org/problem?id=1609
题目大意: 有一些块,每个块有两个参数li mi, 如果有块1(l1,m1),块2(l2,m2),如果满足l1>=l2 && m1>=m2 块1就可以叠在块2上面,反块2能叠放在块1上面,问有n个块,最多能叠多少个块......先根据li从小到大排序,再按mi从小到大排序,对 mi 求最长不递减子序列
顺便复习了二分求 最长子序列。
二分求: 0ms
#include<cstdio> #include<algorithm> using namespace std; struct W { int l; int m; }w[10100]; int cmp(W a,W b) { if(a.l!=b.l) { return a.l<b.l; }else{ return a.m<b.m; } } int main() { int n; scanf("%d",&n); while(n!=0) { int dp[10100]={0};//长度为Len的数字 for(int i=0;i<n;i++) { scanf("%d %d",&w[i].l,&w[i].m); } sort(w,w+n,cmp);//按l从小到大排序 dp[1]=w[0].m; int rr=1; for(int i=1;i<n;i++) { int l=1; int r=rr; //用二分 while(l<=r) { int mid=(l+r)/2; if(dp[mid]>w[i].m) { r=mid-1; }else{ l=mid+1; } } if(l>rr) { rr=rr+1; dp[rr]=w[i].m; }else{ dp[l]=min(dp[l],w[i].m); } } printf("%d\n",rr); scanf("%d",&n); } printf("*\n"); return 0; }传统求:16ms
#include<cstdio> #include<algorithm> using namespace std; struct W { int l; int m; }w[20100]; int cmp(W a,W b) { if(a.l!=b.l) { return a.l<b.l; }else{ return a.m<b.m; } } int max(int a,int b) { if(a>=b)return a; return b; } int main() { int n; scanf("%d",&n); while(n!=0) { for(int i=0;i<n;i++) { scanf("%d %d",&w[i].l,&w[i].m); } sort(w,w+n,cmp);//按l从小到大排序 int dp[20100]={1}; int ans=1; for(int i=1;i<n;i++) { int tmp=0; for(int j=i-1;j>=0;j--) { if(w[i].m>=w[j].m) { tmp=max(tmp,dp[j]); } } dp[i]=tmp+1; ans=max(ans,dp[i]); } printf("%d\n",ans); scanf("%d",&n); } printf("*\n"); return 0; }