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;
}
}