zoukankan      html  css  js  c++  java
  • POJ-1456 Supermarket 销售商品【贪心】+【并查集】

    题目链接:http://poj.org/problem?id=1456

    题目大意:

    有N件商品,分别给出商品的价值和销售的最后期限,只要在最后日期之前销售处,就能得到相应的利润,并且销售该商品需要1天时间。

    问销售的最大利润。

     

    我开始的代码:(贪心策略有问题,因为我当时以为过期时间短的商品要优先卖掉,实际上不是这样的)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define MAXN 10000+100
    
    struct node
    {
        int val;
        int day;
    };
    
    bool mysort(node a, node b)      //按照天数从小到大排序,若天数相同,就按价格从大到小排序
    {
        if (a.day != b.day)return a.day < b.day;                 
        return a.val > b.val;                                     
    }
    
    int main()
    {
        int n;
        while (scanf("%d", &n) != EOF)
        {
            int i, j; int sum = 0;
            node dday[MAXN];
            dday[0].day = 0; dday[0].val = 0;
            for (int i = 1; i <=n; i++)
            {
                scanf("%d%d", &dday[i].val, &dday[i].day);
            }
            sort(dday+1, dday + n+1,mysort);    //注意这里我是从i=1,开始存数据的,所排序的时候也要从i=1开始排序
            int ans = 0;
            for (i = 1; i <= n; i++)
            {
                if (dday[i].day != dday[i - 1].day)
                {
                    ans += dday[i].day - dday[i - 1].day-1;    //dday[i-1]到dday[i]之间空闲的天数,可以存起来,留给后面时间冲突的天数使用
                    sum += dday[i].val;
                }
                else
                {
                    if (ans>0)
                    {
                        ans--;                   //若之前有空余的天数,那么可以拿一天留到现在来销售
                        sum += dday[i].val;
                    }
                }
            }
            printf("%d
    ", sum);
        }
        return 0;
    }
    View Code

    虽然能过样例,但是还有一些情况没有想到。比如,不一定要过期时间越早的商品越先销售,因为,如果后面有价值更大的商品由于时间的冲突不能卖出的话,完全可以舍弃之前销售价值最小的商品,来卖这件价值更大的商品。

    比如数据 :

    5 1 3 15 2 5 3 20 2 10 1

    正确答案为 40 而我的代码答案为35 

    然后换另一种贪心思想

    将商品的价值从大到小排序,找到销售的最大期限,用visit数组标记,如果它的期限没有被占用,就在该天销售,如果占用,则从它的前一天开始向前查找有没有空闲的日期,如果有则占用。这样就可以得到最大销售量。

    
    
    #include<iostream>  
    #include<cstdio>  
    #include<cstring>  
    #include<algorithm>  
    using namespace std;
    #define N 10010  
    bool visit[N];
    
    struct node
    {
        int profit, deadline;
    }p[N];
    
    bool operator <(node a, node b)
    {
        return a.profit > b.profit;
    }
    
    int main()
    {
        int num;
        int maxprofit;
        while (~scanf("%d", &num))
        {
            maxprofit = 0;
            memset(visit, false, sizeof(visit));
            for (int i = 1; i <= num; ++i)
            {
                scanf("%d %d", &p[i].profit, &p[i].deadline);
            }
            sort(p + 1, p + num + 1);            //注意这里是从p+1开始排序
            for (int i = 1; i <= num; ++i)       //优先价值最大
            {
                if (!visit[p[i].deadline])
                {
                    maxprofit += p[i].profit;
                    visit[p[i].deadline] = true;
                }
                else
                {
                    for (int j = p[i].deadline - 1; j >= 1; --j)
                    {
                        if (!visit[j])
                        {
                            maxprofit += p[i].profit;
                            visit[j] = true;
                            break;
                        }
                    }
                }
            }
            printf("%d
    ", maxprofit);
        }
        return 0;
    }
    
    
    

     并查集做法,原理与上面差不多

    #include<iostream>  
    #include<cstdio>  
    #include<cstring>  
    #include<algorithm>  
    using namespace std;
    #define N 10010  
    int pre[N];
    
    struct node
    {
        int profit, deadline;
    }p[N];
    
    bool operator < (const node& a, const node& b)
    {
        return a.profit > b.profit;
    }
    
    int find(int x)             //寻找该点的根节点
    {
        int root, temp;
        root = x;
        while (root != pre[root])
            root = pre[root];
        while (x != root)       //压缩路径
        {
            temp = pre[x];
            pre[temp] = root;
            x = temp;
        }
        return root;
    }
    
    int main()
    {
        int num;
        int root;
        int maxprofit;
        while (~scanf("%d", &num))
        {
            maxprofit = 0;
            for (int i = 1; i < N; ++i)        //注意这里i小于的是N,不是num
                pre[i] = i;
            for (int i = 0; i < num; ++i)
                scanf("%d%d", &p[i].profit, &p[i].deadline);
            sort(p, p + num);
            for (int i = 0; i < num; ++i)        
            {
                root = find(p[i].deadline);        
                if (root > 0)
                {
                    pre[root] = root - 1;           
                    maxprofit += p[i].profit;
                }
            }
            printf("%d
    ", maxprofit);
        }
        return 0;
    }
    
    

    2018-04-21 

  • 相关阅读:
    Apache 浏览器访问限制配置
    Apache 防盗链配置
    Apache 静态缓存配置
    Apache 日志管理
    Apache 域名跳转配置
    搭建完全分布式的hadoop[转]
    Laravel Cheat 表 http://cheats.jesse-obrien.ca/#
    spring-data-mongodb必须了解的操作
    Java MongoDB 资料集合
    MongoDB分片技术[转]
  • 原文地址:https://www.cnblogs.com/00isok/p/8901174.html
Copyright © 2011-2022 走看看