zoukankan      html  css  js  c++  java
  • poj1456 Supermarket 贪心+并查集

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

    题意:有n个物品(0 <= n <= 10000) ,每个物品有一个价格pi和一个保质期di (1 <= pi <= 10000, 1 <= di <= 10000),物品必须在保质期之前卖出。且每天只能卖出一个物品,问如何安排才能使卖出的总价格最大。

    这道题贪心的思想很明显,先将物品的价格按照从大到小排序,再按照该顺序卖物品,如果存在不超过保质期的最大可用日期,则该物品能够卖出,并将这一天标记。关键在于如何找这个日期,就是在一个有序序列中查找小于等于当前日期的最大值,再将其删除,继续查找。这个可以用set来做。

    #include <iostream>
    #include <algorithm>
    #include <stdio.h>
    #include <stack>
    #include <set>
    #include <istream>
    #include<queue>
    #include<stack>
    #include <cstring>
    #include <string>
    //#include <climits>
    using namespace std;
    struct products {
    	int money, day;
    };
    bool cmp(products a, products b) {
    	if (a.money != b.money)
    		return a.money > b.money;
    	return a.day>b.day;
    }
    int main() {
    	int n;
    	while (scanf("%d", &n) != EOF) {
    		set<int> s;
    		products *p = new products[n];
    		int md = 0;
    		for (int i = 0;i < n;i++) {
    			scanf("%d%d", &p[i].money, &p[i].day);
    			md = max(p[i].day, md);
    		}
    		for (int i = 1;i <= md;i++)
    			s.insert(i);
    		sort(p, p + n, cmp);
    		int ans = 0;
    		for (int i = 0;i < n && !s.empty();i++) {
    			if (*s.begin() > p[i].day)
    				continue;
    			set<int>::iterator iter = s.upper_bound(p[i].day);
    			iter--;
    			//cout << *iter << -1 << endl;
    			if (*iter <= p[i].day) {
    				ans += p[i].money;
    				s.erase(iter);
    			}
    		}
    		printf("%d
    ", ans);
    		delete[]p;
    	}
    }
    

      

    除了这种解法外,我们还可以用并查集来维护,初始化每个日期i的父亲为自己,当当前的日期i被占用后,将其父亲设为前一天的日期i-1,每次查找i的最大可用日期即查找i的祖先即可,由于使用路径压缩,所以查找的复杂度很低,比用set块

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    using namespace std;
    class union_find_set {
    public:
    	union_find_set(int n) {
    		fa = new int[n];
    		rank = new int[n];
    		for (int i = 0; i < n; i++)
    			fa[i] = i;
    	}
    	~union_find_set()
    	{
    		delete fa,rank;
    	};
    	int find(int x) {
    		if (fa[x] == x)
    			return x;
    		return fa[x] = find(fa[x]);
    	}
    	void unite(int x, int y) {
    		x = find(x);
    		y = find(y);
    		if (x == y)
    			return;
    		if (rank[x] < rank[y])
    			fa[x] = y;
    		else {
    			fa[y] = x;
    			if (rank[x] == rank[y])
    				rank[x]++;
    		}
    	}
    	bool same(int x, int y) {
    		if (find(x) == find(y))
    			return 1;
    		return 0;
    	}
    	int n;
    	int *fa,*rank;
    };
    
    
    struct products {
    	int money, day;
    };
    
    bool cmp(products a, products b) {
    	return a.money > b.money;
    }
    int main() {
    	int n;
    	while (scanf("%d", &n) != EOF) {
    		products *p = new products[n];
    		int md = 0;
    		for (int i = 0;i < n;i++) {
    			scanf("%d%d", &p[i].money,&p[i].day);
    			md = max(p[i].day, md);
    		}
    		union_find_set P(md + 1);
    		sort(p, p + n, cmp);
    		int ans = 0;
    		for (int i = 0;i < n;i++) {
    			int t = P.find(p[i].day);
    			if (t > 0) {
    				ans += p[i].money;
    				P.fa[t] = t - 1;
    			}
    		}
    		printf("%d
    ", ans) ;
    		delete p;
    	}
    }
    

      

  • 相关阅读:
    ios中的几种多线程实现
    在mac下使用终端管理svn
    关于UIScrollViewDelegate协议中每个回调函数的意义及执行顺序的理解
    UIView 及其子类对象 抖动效果的实现
    ios、andriod、cocos2d 视图层次理解
    委托  通知中心   监听/观察
    iphone 中使用苹果禁用的私有Framework
    关于苹果官方网站Reachability检测网络的总结
    iOS设备的分辨率
    ios开发多线程、网络请求的理解 错误码的理解
  • 原文地址:https://www.cnblogs.com/dlutjwh/p/10709429.html
Copyright © 2011-2022 走看看