题目大意:一张宽为w,长为h的明信片,有n (n≤5000) 个信封,每个信封有其长和宽,一个信封能装的东西必须长宽严格小于自身的长宽,不可以旋转。问装这个明信片最多能用多少信封。
题解:首先去掉所有长宽不大于h和w的信封,然后对信封按照长或宽为关键字排序。
dp[i]
表示最外层是第
i
个信封最多能用多少个信封,记录一下从哪个状态转移过来。总复杂度
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5005;
const int inf = 0x3f3f3f3f;
struct node{
int h,w;
int id;
bool operator<(const node &a)const{
return (w==a.w)?(h<a.h):(w<a.w);
}
}en[maxn];
int dp[maxn];
int out[maxn];
void print(int x){
if(x == -1) return ;
print(out[x]);
printf("%d ",en[x].id);
}
int main(){
int nn,w,h;
memset(out,-1,sizeof(out));
scanf("%d%d%d",&nn,&w,&h);
int n = 0;
for(int i = 0;i < nn;i++){
int x,y;
scanf("%d%d",&x,&y);
if(x<=w||y<=h) continue;
en[n].w = x;
en[n].h = y;
en[n++].id = i+1;
}
sort(en,en+n);
for(int i = 0;i < n;i++) dp[i] = 1;
for(int i = 1;i < n;i++){
for(int j = 0;j < i;j++){
if(en[j].w<en[i].w&&en[j].h<en[i].h){
if(dp[i]<=dp[j]+1){
dp[i] = dp[j]+1;
out[i] = j;
}
}
}
}
int ans = 0,x = -1;
for(int i = 0;i < n;i++){
//printf("i=%d %d %d %d\n",i,dp[i],a[i],b[i]);
if(ans < dp[i]){
ans = dp[i];
x = i;
}
}
printf("%d\n",ans);
print(x);
return 0;
}