CF 4D Mysterious Present

題目大意:一張寬爲w,長爲h的明信片,有n(n5000) 個信封,每個信封有其長和寬,一個信封能裝的東西必須長寬嚴格小於自身的長寬,不可以旋轉。問裝這個明信片最多能用多少信封。

題解:首先去掉所有長寬不大於h和w的信封,然後對信封按照長或寬爲關鍵字排序。dp[i] 表示最外層是第i 個信封最多能用多少個信封,記錄一下從哪個狀態轉移過來。總複雜度O(n2+nlogn)

#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章