#2016京东实习生笔试之生日礼物

题目描述

BF的生日快到了,这一次,小东决定为BF送一份特别的生日礼物为其庆生。作为高智商中的佼佼者,BF在国外求学,因此小东无法与之一起庆生。小东计划送一个生日卡片,并通过特别的包装让BF永远难忘。

她决定把卡片套装在一系列的信封A = {a1,  a2,  …,  an}中。小东已经从商店中购买了很多的信封,她希望能够用手头中尽可能多的信封包装卡片。为防止卡片或信封被损坏,只有长宽较小的信封能够装入大些的信封,同尺寸的信封不能套装,卡片和信封都不能折叠。

小东计算了邮寄的时间,发现她的时间已经不够了,为此找你帮忙包装,你能帮她吗?

输入
输入有若干组,每组的第一行包含三个整数n, w, h,1<=n<=5000, 1<=w, h<=10^6,分别表示小东手头的信封数量和卡片的大小。紧随其后的n行中,每行有两个整数wi和hi,为第i个信封的大小,1<=wi, hi<=10^6。
样例输入
2 1 1
2 2
2 2
3 3 3
5 4
12 11
9 8

输出
对每组测试数据,结果第一行中输出最多能够使用的信封数量,结果第二行中按使用顺序输出信封的编号。由于小东有洁癖,她对排在前面的信封比较有好感,若有多个信封可用,她喜欢用最先拿到的信封。另外别忘了,小东要求把卡片装入能够装的最小信封中。
如果卡片无法装入任何信封中,则在单独的行中输出0。

样例输出
1
1
3
1 3 2

解题思路:我们首先定义一个结构体,存放信封的长,宽,及其索引位置,然后把不能装卡片的信封去除掉(长宽较小的), 然后根据长或宽进行一个排序,这样就可以转化成一个最长递增子序列问题来求解了,2层循环动态规划就很容易求解了。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct Node
{
    int width;
    int height;
    int index;   //节点的位置(索引)
    Node(int w, int h, int idx) :width(w), height(h), index(idx) {}
};
bool cmp(Node node1, Node node2)
{
    if (node1.width < node2.width)
        return true;
    if (node1.width == node2.width&&node1.height < node2.height)
        return true;
    if (node1.width == node2.width&&node1.height==node2.height&&node1.index<node2.index)
        return true;
    return false;
}
int main()
{
    int i, j, k, n, temp1, temp2, w, h;
    while (cin >> n >> w >> h)
    {
        vector<Node> vec;
        for (i = 0; i < n; i++)
        {
            cin >> temp1 >> temp2;
            if(temp1>w&&temp2>h) //只考虑比卡片大的信封
                vec.push_back(Node(temp1, temp2, i + 1));
        }
        sort(vec.begin(), vec.end(), cmp);
        n = vec.size();
        if (n == 0)
            cout << 0 << endl;
        else
        {
            vector<int> a(n, 1), prev(n, -1), b;   //最长递增子序列
            for (i = 1; i < n; i++)
            {
                for (j = 0; j < i; j++)
                {
                    if (vec[i].width > vec[j].width&&vec[i].height > vec[j].height)
                    {
                        if (a[i] < a[j] + 1)
                        {
                            a[i] = a[j] + 1;
                            prev[i] = j;
                        }
                    }
                }
            }
            int res = 0, lastIndex = -1;
            for (i = 0; i < n; i++)
            {
                if (a[i] > res)
                {
                    res = a[i];
                    lastIndex = i;
                }
            }
            cout << res << endl;
            while (lastIndex != -1)
            {
                b.push_back(vec[lastIndex].index); //存放路径
                lastIndex = prev[lastIndex];
            }
            reverse(b.begin(), b.end());
            for (i = 0; i < b.size() - 1; i++)
                cout << b[i] << " ";
            cout << b[i] << endl;
        }
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值