POJ 1456 Supermarket

VJ题目地址

题意:n种商品,每种都有一个限定卖出的时间,如果在限定时间内没有卖出,则无法再卖出。每个单位时间内,只允许卖出一件商品。求给出的这组商品利润最高多少。

解题思路是用并查集来处理区间,这题的区间是卖出时间的限制。

首先取得最大的商品时间,然后在这个最大区间内,初始化dad数组,使每个时间都指向自己,这表明这个时间没有被使用。

当这个时间有商品卖出时,则需要把这个时间 t 指向 t-1 这表明,这个时间已经被使用了,接下来如果有限定时间为 t 的商品,那么它最多也只能在t-1那个时间卖出,因为时间只能往前推。

以上保证了一定在合法时间内卖出商品,那么如何保证最后的利润最高?

直接按商品价格从高到低排序,每次取利润最高的出来,判断下这个商品在限定时间内可不可以被卖出即可。

以题目中的第二个测试用例举例:

20 1 ||  2 1 ||  10 3 || 100 2 ||  8 2 ||  5 20 ||  50 10  首先排序---> 100 2 || 50 10 || 20 1 || 10 3 || 8 2 || 5 20 || 2 1

1.拿到100 此时 dad[2]=2可用,那么res+100,变更dad[2]=1        res=100

2.拿到50   此时 dad[10]=10可用,那么res+50,变更dad[10]=9    res=150

3.拿到20   此时 dad[1]=1可用,那么res+20,变更dad[1]=0     res=170

4.拿到10   此时dad[3]=3可用,那么res+10,变更dad[3]=2           res=180

5.拿到8     此时dad[2]=1   dad[1]=0说明2之前的时间都用完了 因此不可用

6.拿到5     此时dad[20]=20可用,那么res+5,变更dad[20]=19         res=185 

7.拿到2     此时dad[1]=0 说明1之前的时间都用完了 因此不可用

最后得到结果res=185


以上就是用并查集的思想来管理区间问题的过程

代码:

import java.util.Arrays;
import java.util.Scanner;
class Prod implements Comparable<Prod>{
	int p,t;

	public Prod(int p, int t) {
		this.p = p;
		this.t = t;
	}

	@Override
	public int compareTo(Prod o) {
		return o.p-this.p;
	}
}
public class Main {
	static Scanner sc=new Scanner(System.in);
	static int n,max,res;
	static int dad[]=new int[10010];
	static Prod [] p=new Prod[10010];
	static void init(){
		for(int i=0;i<=max;i++){
			dad[i]=i;
		}
	}
	static int find(int x){
		if(x==dad[x]) return x;
		else{
			dad[x]=find(dad[x]);
			return dad[x];
		}
	}
	public static void main(String[] args) {
		while(sc.hasNext()){
			n=sc.nextInt();
			max=0;
			res=0;
			for(int i=0;i<n;i++){
				p[i]=new Prod(sc.nextInt(),sc.nextInt());
				max=Math.max(max,p[i].t);
			}
			Arrays.sort(p, 0, n);
			init();
			int tmpd;
			for(int i=0;i<n;i++){
				tmpd=find(p[i].t);
				if(tmpd>0){
					res+=p[i].p;
					dad[tmpd]=tmpd-1;
				}
			}
			
			
			System.out.println(res);
		}

	}

}



当然本身这题最明显的是贪心思想,并查集只是拿来优化,纯贪心应该是可以A的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值