题意: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);
}
}
}