Description
给出贺卡的宽和高w,hw,h以及nn个信封的宽和高,现在想用尽可能多的信封包起这个贺卡,要求贺卡的宽和高分别严格比最小信封的宽和高小,小信封放在大信封里也有相同的要求,问最多可以套多少个信封,并按规模从小到大输出这些信封的编号,如果没有信封可以放下这张贺卡则输出−1−1
Input
第一行三个整数n,w,hn,w,h表示信封数量和贺卡的宽高,之后nn行每行两个整数
Output
输出最多可以套的信封数量以及这些信封的编号
Sample Input
3 3 3
5 4
12 11
9 8
Sample Output
3
1 3 2
Solution
把放不下贺卡的信封排除,把剩下的信封按宽度升序排序,以表示到前ii个信封中最多可以选多少个,那么有,其中jj需满足且第jj个信封的宽高分别比第个信封的宽高小,在转移过程中记录路径,最后选取dpdp值最大的编号为最大信封,依据转移过程中记录的路径往前找到所选信封的编号即可
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=5005;
int n,m,w,h,dp[maxn],pre[maxn];
struct node
{
int w,h,id;
bool operator<(const node &b)const
{
if(w==b.w)return h<b.h;
return w<b.w;
}
}a[maxn];
int main()
{
scanf("%d%d%d",&n,&w,&h);
m=0;
for(int i=1;i<=n;i++)
{
int ww,hh;
scanf("%d%d",&ww,&hh);
if(ww>w&&hh>h)a[++m]=(node){ww,hh,i};
}
if(m==0)printf("0\n");
else
{
sort(a+1,a+m+1);
dp[0]=0;
for(int i=1;i<=m;i++)
{
int pos=0;
for(int j=1;j<i;j++)
if(a[j].w<a[i].w&&a[j].h<a[i].h)
if(dp[j]>dp[pos])pos=j;
dp[i]=dp[pos]+1;
pre[i]=pos;
}
int pos=1;
for(int i=1;i<=m;i++)
if(dp[i]>dp[pos])pos=i;
printf("%d\n",dp[pos]);
vector<int>ans;
while(pos)
{
ans.push_back(a[pos].id);
pos=pre[pos];
}
for(int i=ans.size()-1;i>=0;i--)printf("%d%c",ans[i],i==0?'\n':' ');
}
return 0;
}