目录
第一题:打水问题(贪心)
解析:
题目给定K个水龙头和n个需要打水的人,每个人打水所要花费的时间不同,求所有人等待时间总和的最小值,这题其实很简单,算是一个生活类的题。一堆人去打水,你要进行合理的分配,那么怎么分配?
生活告诉你:花费时间少的人先打水,花费时间多的人后打水。那么我们将所有人所花费的时间进行排序,然后依次进入打水
不难发现 第i个人会在第i%k的位置打水,这边的i我们从0开始,这样就刚好对应上了;
然后求的是所有人的等待时间总和,那么后面上来打水的人等待的时间应该是和他在同一个水龙头处并且比他先打水的人的时间总和
举例:2个水龙头,6个人
1 2 3 4 5 6
1号水龙头是 1 3 5;2号水龙头是 2 4 6
一号水龙头:
没人比1号早,所以1号等待时间0;
1号比3号早,所以3号等待1;
1号和3号比5号早,所以5号等待4
二号水龙头
没人比2号早,所以2号等待时间0;
2号比4号早,所以4号等待2;
2号和4号比6号早,所以6号等待6
总时间就是:1+4+2+6=13;
代码:
import java.util.Arrays;
import java.util.Scanner;
public class 打水问题 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();//n个人
int m=sc.nextInt();//m个水龙头
int []arr=new int[m];//m个水龙头
int []brr=new int[n];//n个人
for (int i=0;i<n;i++){
brr[i]=sc.nextInt();
}
int s=0;
Arrays.sort(brr);//按照每个人打水时间排序;
for (int i=0;i<n;i++){
s+=arr[i%m];
arr[i%m]+=brr[i];
}
System.out.println(s);
}
}
第二题:夺宝奇兵(动态规划)
解析:
有没有很熟悉的感觉?这就是dp 的经典题:数字三角形
从下往上,要求取到的值总和最大,并且每次只能往上或者左上方走
但是这样的思考我个人觉得是有点点困难了,感觉复杂变化和边界值不好掌控;
个人思路:从上往下
因为题目要求到达山顶,那么最上面的值必定获得,然后就可以考虑:在它下面一层值的最大值怎么获得?
走到最上面要最大,那么只能从它的下一层的走到3/8时两个数的最大值中去选择;
这样子的话是从下往上去运算,dp转移公式:arr[a][b]+=Math.max(arr[a+1][b],arr[a+1][b+1]);
那么现在看一下从上往下运算:
这样子就算从上往下,和从下往上的方法是相同的,不过多了一个判断最下方一层的最大值;
dp转移方程:arr[a][b]+=Math.max(arr[a-1][b],arr[a-1][b-1]);
代码:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n=scanner.nextInt();
int [][]arr=new int[n][n];
for(int i=0;i<n;i++){
for(int j=0;j<=i;j++){
arr[i][j]=scanner.nextInt();
}
}
int s=arr[0][0];
for(int i=1;i<n;i++){
for(int j=0;j<=i;j++){
if(j==0)
arr[i][j]=arr[i-1][j]+arr[i][j];
else
arr[i][j]=Math.max(arr[i-1][j],arr[i-1][j-1])+arr[i][j];
}
}
Arrays.sort(arr[n-1]);
System.out.println(arr[n-1][n-1]);
}
}
第三题:调手表(动态规划)
解析:
这题其实不难,唯一的一点:一次只能+1或者+k;然后将1-(n-1)中的所有所有是数字都出现的情况下的最小的最大值,比如 1-5;一次只能按+1或者+2;那么第一次可以+1,也可以+2;这样就完成了1和2,第二次1+1或者1+2;2+1或者2+2;就可以出现2/3/4,那么还有一个5没有出现过,就需要再按一次,满足所有数值都出现的情况下,最小的最大值为多少?
我们每一次判断:如果这个数是k的倍数,那么这个数的最小次数就是i/k;
如果不是,那么我们要考虑最坏的情况:上一个位置的次数按一次+1到达;
然后再分析这个值可能出现的优化情况:通过n次按+k后可以到达该值,且n次小于最坏情况,则为优化解
运算完后找到最大值即可
代码:
import java.util.Arrays;
import java.util.Scanner;
public class 调手表 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();//时间长度
int k=sc.nextInt();//一次增长
int []arr=new int[n];
for (int i=1;i<n;i++){
if (i%k==0){
arr[i]=i/k;
}else{
arr[i]=arr[i-1]+1;
for ( int j = 1; j <= arr[i-1]+1 ; j++ ) {
if ( ( k * j ) % n == i ) {
arr[i] = j;
break;
}
}
}
}
Arrays.sort(arr);
System.out.println(arr[n-1]);
}
}