JAVA-蓝桥杯-算法提高 打水问题

问题描述
  N个人要打水,有M个水龙头,第i个人打水所需时间为Ti,请安排一个合理的方案使得所有人
  的等待时间之和尽量小。
输入格式
  第一行两个正整数N M 接下来一行N个正整数Ti。
  N,M<=1000,Ti<=1000
输出格式
  最小的等待时间之和。(不需要输出具体的安排方案)
样例输入
7 3
3 6 1 4 2 5 7
样例输出
11
提示
  一种最佳打水方案是,将N个人按照Ti从小到大的顺序依次分配到M个龙头打水。
  例如样例中,Ti从小到大排序为1234567,将他们依次分配到3个龙头,则去龙头
  一打水的为147;去龙头二打水的为2,5;去第三个龙头打水的为3,6。
  第一个龙头打水的人总等待时间 = 0 + 1 + (1 + 4) = 6
  第二个龙头打水的人总等待时间 = 0 + 2 = 2
  第三个龙头打水的人总等待时间 = 0 + 3 = 3
  所以总的等待时间 = 6 + 2 + 3 = 11

代码如下:

import java.util.Arrays;
import java.util.Scanner;


public class 打水问题 {

	/**
	 * @param args
	 * 思路:这道题目我们需要求等的时间最少,那我们需要把接水时间长的人放到最后来接水,这样等的时间是最少的
	 * 1.先对用户输入的数据进行排序
	 * 2.然后 给他们进行分组,按照水龙头的个数来一排分几个,这个时候我们需要定义一个二维数组
	 * 3.最后来累加总的时间,(1)先来累加前a/b排需要等的总时间,当然第一排不需要等,这个时候我们需要进行累加前a/b排
	 * 人数等的总时间,(2)因为a/b还不能整除,所以肯定还剩的有人在最后一排,但是没有排满,那我们就应该再求一下最后一排人等的总时间
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		int a = sc.nextInt();
		int b = sc.nextInt();
		int arr []=new int[a];  //储存用户输入的一组数据
		for (int i = 0; i <a; i++) {
			arr[i]=sc.nextInt();
		}
		Arrays.sort(arr); //从小到大排序
		int row = (a/b)+1;  //定义二维数组的行数
		int arr1[][]=new int[row][b]; //定义一个二维数组来对用户输入的数据进行按顺序分配成row行b列
		int s = 0;  //定义变量用来计数,
		for (int i = 0; i <row; i++) {
			for (int j = 0; j <b; j++) {
				if (s<a) { //防止越界
					arr1[i][j]=arr[s];
					s++;
				}
			}
		}
		//接下来就是这么累加总的时间,
		int sum = 0; //用来存储最短的时间总和
		for (int t = 1; t <a/b; t++) {  //第一层循环用来判断循环次数
			for (int i = 0; i <t; i++) { 
				for (int j = 0; j <b; j++) {
					sum+=arr1[i][j];  //对接水的时间进行累加
				}
			}
		}
		//前面的循环只累加整行的数据,下面的循环是来累加a%b后剩下的人数应该等多长时间
		for (int i = 0; i <row-1; i++) {  
			for (int j = 0; j <a%b; j++) {
				sum+=arr1[i][j];  //因为后面的人数等的时间应该要把前面所有人等的时间全部加起来,所以我们只要在之前的sum基础上继续累加就可以了
			}
		}
		System.out.println(sum);  //最后输出总时间
	}
}

程序调试结果如下:

48 8
38 23 41 16 42 15 22 15 8 17 39 19 5 16 23 44 30 5 26 14 44 21 2 31 40 18 6 1 48
 5 15 48 25 42 21 30 24 12 26 14 12 35 37 45 46 27 18 39 

结果:1887
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值