codeforces 4D. Mysterious Present

题目链:D. Mysterious Present

题意:

给n个信封,宽和高严格大于另一个信封就可以将他装在里面,信封宽高严格大于卡片就能将卡片装在里面。求最大能套几个信封。

思路:

这题就是和求最长递增子序列一样。先筛掉宽高比卡片小的,然后排序(按长度,宽度都可以)。然后dp,dp[i]的长和宽严格大于dp[j] dp[i]={1–(i-1}中最大的dp[j]+1;遍历完序列找出最大的dp就是答案。这题多了个保存路径。用pre存路径 node存最大的值所对应的节点。pre存上一个节点。比如 最大的dp[i]是在dp[j]的基础上+1,那么pre[i]=j;

代码

#include<iostream>
#include<vector>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
struct env
{
    env(int x, int y, int z) :w(x), h(y), num(z) {
    }
    int w, h, num;
    bool operator<(const env &a)const
    {
        return w<a.w;
    }
};
vector<struct env>v; //存比卡片大的信封
vector<int>ans;  //存路径
//res用来dp 存第i个信封时,最大值。 maxn存最长序列的长度,node存最长序列的最后一个点。
int pre[5100], res[5100], maxn = -1, node = -1;  
//将pre初始化为-1;
void init() {
    for (int i=0; i < 5010; ++i) {
        pre[i] = -1;
    }
}
int main()
{
    init();
    int n, w, h, i, j;
    cin >> n >> w >> h;
    for (i = 1; i <= n; ++i) {
        int W, H;
        cin >> W >> H;
        if (W>w&&H>h)v.emplace_back(W, H, i);
    }
    sort(v.begin(), v.end());
    if (v.size() == 0)cout << "0";
    else {
        //dp
        for (i = 0; i<v.size(); ++i) {
            res[i] = 1;
            for (j = 0; j<i; ++j) {
                if (v[j].w<v[i].w&&v[j].h<v[i].h&&res[j] + 1>res[i]) {
                    res[i] = res[j] + 1;
                    pre[i] = j;
                }
            }

            if (maxn<res[i])
            {
                maxn = res[i];
                node = i;     //跟新节点和最大值
            }
        }
        cout << maxn << endl;
        //倒推求路径 存在ans里面
        while (node!=-1) {
            ans.push_back(node);
            node = pre[node];
        }
         //输出路径
        for (i = ans.size() - 1; i >= 0; --i)
            cout << v[ans[i]].num << " ";
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/PinappleMi/article/details/80149650