题意整理
- 总共有m个冰淇淋要运输,运输车一次最多装n个,来回一趟各需t分钟。
- 现在每个冰淇淋都有一个制作时间,求怎样运输花费时间最短,最短时间下怎样运输次数最少。
方法一(动态规划)
1.解题思路
- 状态定义:表示运输完第i个物品并且回到工厂所需要的最短时间。
- 状态初始化:将所有状态置为Integer型整数最大值。
- 状态转移:如果第i个冰淇淋之前有生产冰淇淋,则最多从第个冰淇淋算起,找到运完这一组冰淇淋(最多n个一组)所需的时间,如果时间小于当前的状态,则进行跟新,同时记录前驱状态。
- 运完最后一个冰淇淋的时间即是最短花费时间,运输次数可根据前驱数组倒推出来。
动图展示:
2.代码实现
import java.util.*; public class Solution { /** * 两个数表示答案 * @param n int整型 一次运输的冰激凌数量 * @param m int整型 总冰激凌数 * @param t int整型 一次运输的时间 * @param c int整型一维数组 表示每个冰激凌制作好时间<1e4 * @return int整型一维数组 */ //Integer型整数最大值 int INF=Integer.MAX_VALUE; public int[] icecream (int n, int m, int t, int[] c) { //记录转移前的状态 int[] pre=new int[m]; //dp[i]表示运输完第i个物品并且回到工厂所需要的最短时间 int[] dp=new int[m]; //初始化 Arrays.fill(pre,INF); Arrays.fill(dp,INF); //排序 Arrays.sort(c); for(int i=0;i<m;i++){ //如果小于n,直接赋值 if(i<n){ dp[i]=c[i]+2*t; } //如果小于n,从0开始算,否则从i-n处开始 int start=Math.max(0,i-n); for(int j=start;j<i;j++){ //计算j+1到i区间的冰淇淋装车运输需要多长时间 int tmp=Math.max(dp[j],c[i])+2*t; //跟新dp[i] if(dp[i]>tmp){ dp[i]=tmp; pre[i]=j; } } } //最少运输次数 int cnt=0; int cur=m-1; //从终点处m-1往前推,直到没有前驱 while(cur!=INF){ cnt++; cur=pre[cur]; } return new int[]{dp[m-1]-t,cnt}; } }
3.复杂度分析
- 时间复杂度:排序的时间复杂度是,主循环体最多执行次,所以最终的时间复杂度为。
- 空间复杂度:需要额外大小为m的dp数组和pre数组,所以空间复杂度为。
方法二(贪心)
1.解题思路
为了运输时间最短,肯定先制作完的,先运走,所以先对数组排序,然后每次尽可能多地往运输车里装,所以每满个运输一次。当有一组不足个时,考虑将其放在前面装车运走,因为运输消耗的时间,刚好可以抵消其它冰淇淋制作的时间。
- 首先对数组排序。
- 然后将所有冰淇淋个一组装车运走,如果有一组不足个,从第个开始,对应次数为。如果每组都是个,则从第个开始,对应次数为
- 注意最后一趟运完不需要返回,所以最后的时间要减去。
2.代码实现
import java.util.*; public class Solution { /** * 两个数表示答案 * @param n int整型 一次运输的冰激凌数量 * @param m int整型 总冰激凌数 * @param t int整型 一次运输的时间 * @param c int整型一维数组 表示每个冰激凌制作好时间<1e4 * @return int整型一维数组 */ public int[] icecream (int n, int m, int t, int[] c) { //排序 Arrays.sort(c); //初始化最短时间,最少次数,从第几个冰淇淋开始运输 int res=0; int cnt=0; int start=0; //如果余数为0,从第n-1个开始,次数为m/n if(m%n==0){ start=n-1; cnt=m/n; } //如果余数不为0,从第m%n-1个开始,次数为m/n+1 else{ start=m%n-1; cnt=m/n+1; } //每隔n个运输一次 for(int i=start;i<m;i+=n){ res=Math.max(res,c[i])+2*t; } //最后一趟不需返回 res-=t; return new int[]{res,cnt}; } }
3.复杂度分析
- 时间复杂度:排序的时间复杂度是,主循环体最多执行次,所以最终的时间复杂度为。
- 空间复杂度:需要额外常数级别的空间,所以空间复杂度为。