生日礼物(京东2016实习生真题)

BF的生日快到了,这一次,小东决定为BF送一份特别的生日礼物为其庆生。作为高智商中的佼佼者,BF在国外求学,因此小东无法与之一起庆生。小东计划送一个生日卡片,并通过特别的包装让BF永远难忘。她决定把卡片套装在一系列的信封A = {a1,  a2,  ...,  an}中。小东已经从商店中购买了很多的信封,她希望能够用手头中尽可能多的信封包装卡片。为防止卡片或信封被损坏,只有长宽较小的信封能够装入大些的信封,同尺寸的信封不能套装,卡片和信封都不能折叠。小东计算了邮寄的时间,发现她的时间已经不够了,为此找你帮忙包装,你能帮她吗?

首先按照信封的长和宽排序,若信封i的长>信封j的长 并且 信封j的款>信封j的宽,才能视为 信封i>信封j, 这样做的原因是:由于小东有洁癖,她对排在前面的信封比较有好感,若有多个信封可用,她喜欢用最先拿到的信封。

排好序后,就可以使用最长递增子序列来求解。http://blog.csdn.net/baidu_28312631/article/details/47426445

注意要丢弃长宽小于生日礼物的信封。

#include<iostream>
#include<vector>
#include<cmath>
using namespace std;


int main() {
    int n;
       unsigned long long w, h;
    while (cin >> n >> w >> h) {
        unsigned long long *W = new  unsigned long long[n], *H = new  unsigned long long[n];//, *S = new  unsigned long long[n];

        //input
        for (int i = 0; i<n; i++) {
            cin >> W[i] >> H[i];
            if (W[i] <= w || H[i] <= h) {
                W[i] = 0;
                H[i] = 0;
            }
            //S[i] = W[i] * H[i];
        }

        //sort
        int *seq = new int[n];
        vector<vector<int>> res;
        for (int i = 0; i<n; i++) {
            seq[i] = i;
        }



        for (int i = n - 1; i>0; i--) {
            for (int j = 0; j<i; j++) {

                if (/*S[seq[j]]>S[seq[j + 1]]*/W[seq[j]]>W[seq[j+1]]&&H[seq[j]]>H[seq[j+1]]) {
                    int t = seq[j];
                    seq[j] = seq[j + 1];
                    seq[j + 1] = t;
                }
            }
        }

        int firstPos = -1;//第一个不为0 的下标。
        for (int i = 0; i<n; i++) {
            res.push_back({});
            if (W[seq[i]] != 0)
            { firstPos = i;
              break;
            }
                

        }

        if (firstPos == -1) {
            cout << 0 << endl;
            continue;
        }



        res[firstPos].push_back(seq[firstPos]);
        //将自身放入序列中;


        int * maxl = new int[n];//记录以seq[i]结束的最长子序列的长度
        for (int i = firstPos; i<n; i++) {
            maxl[i] = 1;
        }

        for (int i = firstPos + 1; i<n; i++) {
            
            int maxPre = -1, maxV = 0;
            
            for (int j = firstPos; j<i; j++) {
                

                if (H[seq[j]] <H[seq[i]] &&W[seq[j]] <W[seq[i]] && maxl[j]>maxV) {
                    maxPre = j;
                    maxV = maxl[j];
                }
            }

                if (maxPre != -1) {
                    maxl[i] = maxl[maxPre]+1;
                    res.push_back( res[maxPre]);
                    res[i].push_back(seq[i]);
                }
                else {
                    res.push_back({ seq[i] });
                }
                

            
        }
        int maxRes = 0, index = firstPos;
        for (int i = firstPos; i<n; i++) {
            if (maxl[i]>maxRes) {
                index = i;
                maxRes = maxl[i];
            }

        }
        cout << maxl[index] << endl;

        for (auto r : res[index])
            cout << r + 1 << " ";
        cout << endl;


    }


    return 0;






}

 

转载于:https://www.cnblogs.com/tacia/p/6676929.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值