生日礼物(京东2016实习生真题)(最长递增子序列,输出长度和序列)
BF的生日快到了,这一次,小东决定为BF送一份特别的生日礼物为其庆生。作为高智商中的佼佼者,BF在国外求学,因此小东无法与之一起庆生。小东计划送一个生日卡片,并通过特别的包装让BF永远难忘。
她决定把卡片套装在一系列的信封A = {a1, a2, ..., an}中。小东已经从商店中购买了很多的信封,她希望能够用手头中尽可能多的信封包装卡片。为防止卡片或信封被损坏,只有长宽较小的信封能够装入大些的信封,同尺寸的信封不能套装,卡片和信封都不能折叠。
小东计算了邮寄的时间,发现她的时间已经不够了,为此找你帮忙包装,你能帮她吗?
输入
输入有若干组,每组的第一行包含三个整数n, w, h,1<=n<=5000, 1<=w, h<=10^6,分别表示小东手头的信封数量和卡片的大小。紧随其后的n行中,每行有两个整数wi和hi,为第i个信封的大小,1<=wi, hi<=10^6。
|
样例输入
2 1 1 2 2 2 2 3 3 3 5 4 12 11 9 8
|
输出
对每组测试数据,结果第一行中输出最多能够使用的信封数量,结果第二行中按使用顺序输出信封的编号。由于小东有洁癖,她对排在前面的信封比较有好感,若有多个信封可用,她喜欢用最先拿到的信封。另外别忘了,小东要求把卡片装入能够装的最小信封中。 如果卡片无法装入任何信封中,则在单独的行中输出0。
|
样例输出
1 1 3 1 3 2
|
时间限制
C/C++语言:1000MS 其他语言:3000MS |
内存限制
C/C++语言:65536KB 其他语言:589824KB |
#include <iostream> #include <cstdio> #include <cmath> #include <cstdlib> #include <algorithm> using namespace std; int n,w,h; struct node { int num; int w; int h; } nodes[5005]; bool cmp(node a,node b) { return a.w<b.w; } //最长递增子序列(输出长度和序列) int maxs; int lists[5005]; int LISS(int len) { int dp[5005]; int pre[5005]; int maxs=1; int k=1; //记录最后一个尾元素的位置 for(int i=1;i<=len;i++) { pre[i]=i; //开始的地方 dp[i]=1; //递增的长度 for(int j=1;j<i;j++) { if(nodes[i].h>nodes[j].h&&dp[i]<dp[j]+1) { dp[i]=dp[j]+1; pre[i]=j; //递增开始的地方 } } if(dp[i]>maxs) { maxs=dp[i]; k=i; } } int j=maxs; while(k!=pre[k]) { lists[j--]=nodes[k].num; k=pre[k]; } lists[j]=nodes[k].num; return maxs; } int main() { while(~scanf("%d",&n)) { maxs=1; int x,y; int g=0; cin>>w>>h; for(int i=1; i<=n; i++) { cin>>x>>y; if(x<=w||y<=h) continue; nodes[++g].w=x; nodes[g].h=y; nodes[g].num=i; } if(g==0) { cout<<"0"<<endl; continue; } sort(nodes+1,nodes+g+1,cmp); int maxs=LISS(g); int cas[5005]; int ww=0; //标记上一个进入递增序列的w值,用来筛掉后面w相同且符合递增的h int l=0; int ii,jj; for(ii=1;ii<=maxs;ii++) { for(jj=1;jj<=g;jj++) { if(lists[ii]==nodes[jj].num) break; } if(nodes[jj].w!=ww) { cas[++l]=lists[ii]; ww=nodes[jj].w; } } cout<<l<<endl; for(int i=1; i<l; i++) { cout<<cas[i]<<" "; } cout<<cas[l]<<endl; } }