[河北师范大学“云淮杯”][D]MJJ玩磁铁(Java)(贪心)

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 137  Solved: 8
[Submit][Status][Web Board][Creator:eetze]

原题链接::Problem D: MJJ玩磁铁

Description

        MJJ在河北的ACM圈子中可谓是小有名气,毕竟当初一个人挑起队秒天秒地秒一切。在训练赛上多次AK江湖传闻一天不A10题晚上就睡不着觉。正是这么刻苦这么努力的MJJ,收货了一大批女粉丝,但是MJJ除了ACM以外却只喜欢玩磁铁。MJJ的班级有(N+1)个同学,(包括他自己)每个人都有手中都有一个磁铁,重量为W。每次MJJ都可以做以下行为之一:
    
1.每次MJJ可以挑战他的一个同学。MJJ选择一个属于他的磁铁,并把这个磁铁和他的同学的磁铁放在桌子上,用一个短距离让这两个磁铁相互吸引。假设桌子是绝对光滑的,两个磁铁会向中间移动。如果MJJ的磁铁速度比同学的磁铁速度慢,MJJ就会取得胜利,并且得到同学手中的磁铁。

2.MJJ极其擅长手工,每次他可以选择自己的两个磁铁,并将它们组合成一个新的磁铁。如果这两块磁铁的重量是U和V,那么新磁铁的重量将是(U+V),而这个操作将会消耗掉他(U+V)个单位的体力。

MJJ在今天的训练后已经非常的累了,所以他将这个问题留给了你。MJJ期望在获得最大的磁铁重量的前提下消耗最少的体力,请计算出MJJ最终的磁铁重量和其消耗的体力。
 

Input

第一行包含一个整数T(1≤T≤6),表示有T个测试用例。
对于每个测试用例:第一行包含一个整数N(1≤N≤100000),表示同学人数。
第二行包含N个整数W1…WN(1≤W≤100000),表示每个同学拥有的磁铁的重量。
最后一行包含一个整数M(1≤M≤100000),表示MJJ磁铁的重量。

Output

对于每个测试用例,首先输出一行“Case #X:”(不带引号,X为测试用例编号,从1开始),然后输出带有两个整数的行:第一个是MJJ最终的磁铁重量,第二个是MJJ所需消耗的体力。

Sample Input

1
3
2 3 6
5

Sample Output

Case #1:
16 31

解题思路:

首先得读懂题的意思,我就是读错意思了,卡了好久。

题中要求最后MJJ手中只有一个磁铁(因为磁铁合并之后就不能拆开了,且是最重的)(PS:我以为MJJ最后剩下的是一堆磁铁)

因为最后MJJ只有一个磁铁,所以应该把之前拥有的磁铁全部合并成一个 sum(前边数之和);

只要sum大于当前同学磁铁重量,那么sum+=Wi;

以此类推,之后都这样,直到sum小于Wi;

现在要求的就是把之前拥有的磁铁合并成一个所耗费的最小体力(之前遍历的时候用 优先级队列 存储磁铁重量);

每次只需要取队列中最小的两个数,相加,再add到队列中,耗费体力值cut+=两数之和;

直到剩余一个值;

答案就是 sum cut;

反思错误:

①题读错意思了,审题啊审题。

②同学们的磁铁不是有序的,要排序!

 

Java代码(用了快读和快输):

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.Queue;

public class Main{
	static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
	static int nextInt() throws IOException {cin.nextToken();return (int)cin.nval;}
	static long nextLong() throws IOException {cin.nextToken();return (long)cin.nval;}
    public static void main(String[] args) throws IOException{
    	int t=nextInt();
    	for(int ti=1;ti<=t;++ti) {
    		int n=nextInt();
    		long[] sco = new long[n];
    		for(int i=0;i<n;++i)sco[i]=nextLong();
    		long m=nextLong();

            //计算开始
    		Arrays.sort(sco);
    		Queue<Long> pq=new PriorityQueue<>();
    		pq.add(m);
    		long sum=m,cut=0;
    		for(int i=0;i<n;++i) {
    			if(sum>sco[i]) {sum+=sco[i];pq.add(sco[i]);}
    			else break;
    		}
    		int size=pq.size();
    		while(size-->1) {
    			long a=pq.remove()+pq.remove();
    			cut+=a;
    			pq.add(a);
    		}
            //计算结束

    		cout.printf("Case #%d:\r\n%d %d\n",ti,sum,cut);
    	}
        cout.flush();
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值