poj 1456

来源:互联网 发布:淘宝运营 数据表格 编辑:程序博客网 时间:2024/06/16 07:09

题目概述

有N个商品,在其保质期dl天内卖掉可得利润v,否则没有利润,卖掉每个商品需要1天,求最大利润

时限

2000ms/6000ms

输入

每组数据第一个整数N,其后N对整数v,dl,输入中空白符会任意出现,输入到EOF为止

限制

1<=N,dl,v<=10000

输出

每行一个数,为所求最大利润

样例输入

4
50 2
10 1
20 2
30 1
7
20 1
2 1
10 3
100 2
8 2
5 20
50 10
3
1 1
100 2
100 2
2
99 1
100 100

样例输出

80
185
200
199

讨论

贪心,对于那些贵的商品,都希望其能在保质期内尽量晚的卖掉,但是无法避免有些由于太便宜而被扔掉,那么每次取最贵的,从保质期这天开始(当然也包括这一天)向前找空闲的一天,将之安排在这一天卖掉,由于已经按利润降序排,故后安排的肯定不如先安排的贵,因而若没找到空闲时间就直接扔掉了,然而从实现层面上,由于需要处理if语句,导致效率受到一定影响,采用优化后的并查集可以进一步加快速度
并查集,基本思想也是继承上面的,但是以并查集表示每一天,如果这天已经安排了,就以前一天为父节点,这样查找时总能找到空闲的一天,如果找到的是第0天,扔掉,这样就避开了很多if语句的处理,从实现层面上,初始化并查集时也不用全初始化,只要把保质期最长的那一天及之前都初始化就可以了
另外uva上也有这个题,但是下面两种方法都会超时

题解装填

贪心:284K,141MS,C++,723B
并查集:284K,63MS,C++,875B

题解代码

贪心:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define INF 0x3f3f3f3f#define MAXN 10004#define memset0(a) memset(a,0,sizeof(a))struct It//每个商品的结构{    int v, dl;//value 利润 deadline 保质期    bool operator<(const It &b)const    {        return v > b.v;    }}its[MAXN];int N;//商品总数int schedule[MAXN];//每天安排销售的商品的利润int fun(){    for (int p = 0; p < N; p++)        scanf("%d%d", &its[p].v, &its[p].dl);//input    sort(its, its + N);    int sum = 0;    for (int p = 0; p < N; p++)        for (int i = its[p].dl; i; i--)//从保质期最后一天枚举            if (!schedule[i]) {//找到空白的一天 题目保证每个商品利润都是正                sum += schedule[i] = its[p].v;                break;            }    return sum;}int main(void){    //freopen("vs_cin.txt", "r", stdin);    //freopen("vs_cout.txt", "w", stdout);    while (~scanf("%d", &N)) {//input        printf("%d\n", fun());//output        memset0(schedule);    }}

并查集:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define INF 0x3f3f3f3f#define MAXN 10004#define memset0(a) memset(a,0,sizeof(a))struct It{    int v, dl;    bool operator<(const It &b)const    {        return v > b.v;    }}its[MAXN];int N;int id[MAXN];//父节点int UFfind(int a){    int p = a;    while (a != id[a])        a = id[a];    return id[p] = a;}int fun(){    int longest = -INF;//最长的保质期    for (int p = 0; p < N; p++) {        scanf("%d%d", &its[p].v, &its[p].dl);//input        longest = max(longest, its[p].dl);    }    sort(its, its + N);    for (int p = 0; p <= longest; p++)//初始化并查集        id[p] = p;    int sum = 0, available;//总利润 空闲的一天    for (int p = 0; p < N; p++)        if (available = UFfind(its[p].dl)) {//找到的是第0天就扔掉了            sum += its[p].v;            id[available]--;//这天已被占用 连到前一天        }    return sum;}int main(void){    //freopen("vs_cin.txt", "r", stdin);    //freopen("vs_cout.txt", "w", stdout);    while (~scanf("%d", &N))//input        printf("%d\n", fun());//output}

EOF

0 0
原创粉丝点击