根堆系列之超市

145. 超市 - AcWing题库

这个题我们先给出做法,然后在解释原理。

我们首先开一个商品类,这个类中储存利润和日期。我们通过输入的商品的数量开个商品数组,然后依据商品的日期由小到大将这个商品的数组升序排列。我们再开一个小根堆,依据商品的利润把商品从小到大存储。这里注意了我们依次扫描原来的商品的数组,如果商品的日期大于我们小根堆的存储的商品的数量我们将商品放入小根堆里。如果等于我们取出小根堆里的头商品,把它的利润跟商品对比,小的话我们把新商品入堆,头商品舍弃。最后我们的堆里所存储的商品的总利润就是我们要求的答案。

我们解释原理吧。首先商品有日期限制,可能最大利润的商品的保质期最短,并且我们考虑卖商品时,保质期长的商品可以第一天卖也可以之后卖可以放后边来考虑,但保质期短的商品只能在前几天卖完。为此我们先把商品的保质期按从小到大排序起来,优先考虑保质期短的商品。然后我们开个小根堆,小根堆主要按照商品的利润把商品从小到大排起来。我们创建完成后,小根堆是空的,我们依次扫描商品数组。堆的大小n就是前n天卖出去的货物。所以当商品的保质期n等于堆的大小时,这意味着我们在前n天已经安排卖的货,但是商品的保质期就到第n天,所以我们需要取出堆里最小的利润商品(也就是我们打算在第前n天卖掉的商品),跟新商品比较,如果小于,就加入新商品否则保留原商品。这就是贪心。这样可以保证,如果利润第一大和第二大的商品都是同一天(例如极端第一天),我们可以选取最大的,如果是在(第n天)我们遍历前n天时可以把保质期长且利润高的物品放到第一天

上代码


import java.awt.FontFormatException;
import java.io.BufferedReader; 
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.AnnotatedWildcardType;
import java.math.BigInteger;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Objects;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Spliterator.OfPrimitive;
import java.util.function.IntToDoubleFunction;
import java.util.function.LongBinaryOperator;
import java.util.TreeMap;
import java.util.TreeSet;
import javax.management.relation.InvalidRelationTypeException;
import javax.print.attribute.standard.JobMessageFromOperator;
import javax.print.attribute.standard.JobPriority;
import javax.swing.table.TableModel;
import javax.swing.text.TabSet;


public class Main {
  public static void main(String[] args) throws IOException  {
Scanner sc=new Scanner(System.in);
BufferedReader br1=new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw1=new PrintWriter(System.out);
while(sc.hasNext()) {
	PriorityQueue<aaa> pq1=new PriorityQueue<>(new Comparator<aaa>() {

		@Override
		public int compare(aaa o1, aaa o2) {
			// TODO Auto-generated method stub
			int a=o1.lirun-o2.lirun;
			return a;
		}

		
		
	});
	int a=sc.nextInt();
	int b=0;
	aaa[] aa1=new aaa[a];
	for(b=0;b<a;b++) {
		int c=sc.nextInt();
		int d=sc.nextInt();
		aa1[b]=new aaa(c, d);
	}
	Arrays.sort(aa1,new Comparator<aaa>() {

		@Override
		public int compare(aaa o1, aaa o2) {
			// TODO Auto-generated method stub
			int a=o1.time-o2.time;
			return a;
		}
	});
	for(b=0;b<a;b++) {
	int d=aa1[b].time;
	int c=aa1[b].lirun;
		int e=pq1.size();
		if(d<=pq1.size()) {
			aaa a2=pq1.poll();
			if(c>a2.lirun) {
				pq1.add(aa1[b]);
			}
			else {
				pq1.add(a2);
			}
		}
		else{
			pq1.add(aa1[b]);
		}
	}
	int answer=0;
	//System.out.println("AAA"+pq1);
	while(pq1.size()>0) {
		aaa a4=pq1.poll();
		answer=answer+a4.lirun;
	}
	System.out.println(answer);
}
  }
}
class aaa{
	int lirun;
	int time;
	public aaa(int lirun, int time) {
		super();
		this.lirun = lirun;
		this.time = time;
	}
	@Override
	public String toString() {
		return "aaa [lirun=" + lirun + ", time=" + time + "]";
	}
	

	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值