算法题型归类整理及同类题型解法思路总结(持续更新)

1、最优路线

通用思路

1、递归

#案例1-最优路测路线

题目描述

评估一个网络的信号质量,其中一个做法是将网络划分为栅格,然后对每个栅格的信号质量计算。

路测的时候,希望选择一条信号最好的路线(彼此相连的栅格集合)进行演示。

现给出 R 行 C 列的整数数组 Cov,每个单元格的数值 S 即为该栅格的信号质量(已归一化,无单位,值越大信号越好)。

要求从 [0, 0] 到 [R-1, C-1]设计一条最优路测路线。返回该路线得分。

规则:

  • 路测路线可以上下左右四个方向,不能对角
  • 路线的评分是以路线上信号最差的栅格为准的,例如路径 8→4→5→9 的值为4,该线路评分为4。线路最优表示该条线路的评分最高。

输入描述

一行表示栅格的行数 R

第二行表示栅格的列数 C

第三行开始,每一行表示栅格地图一行的信号值,如5 4 5

输出描述

最优路线的得分

备注

  • 1 ≤ R,C ≤ 20
  • 0 ≤ S ≤ 65535

用例1

输入

3
3
5 4 5
1 2 6
7 4 6

输出

4

说明

路线为:5→4→5→6→6

用例2

输入

6
5
3 4 6 3 4
0 2 1 1 7
8 8 3 2 7
3 2 4 9 8
4 1 2 0 0
4 6 5 4 3

输出

3

说明

路线为:3→4→6→3→4→7→7→8→9→4→3→8→8→3→4→4→6→5→4→3

代码:

package algorithm.huawei;import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;public class Test61ZuiyouLuxian {static int min = Integer.MAX_VALUE;static List<List<Path>> ll = new ArrayList<List<Path>>();public static void main(String[] args) {Scanner in = new Scanner(System.in);while (in.hasNextInt()) {int m = in.nextInt();in.nextLine();int n = in.nextInt();int[][] mn = new int[m][n];for(int i=0;i<m;i++){for(int j=0;j<n;j++){mn[i][j] = in.nextInt();}in.nextLine();}int min=mn[0][0];List<Integer> li = new LinkedList<Integer>();
//			数据准备完毕dfs(mn,m,n,0,0,min,li);System.out.println(li.get(0));}}private static void dfs(int[][] mn, int m, int n, int i, int j, int min, List<Integer> li) {if(i<0 || j<0 || i>m-1 || j>n-1 || mn[i][j]==-1){return;}if(li.size()>0 && min<=li.get(0)){return;}min = Math.min(min, mn[i][j]);if(i==m-1 && j==n-1){li.clear();li.add(min);}int temp=mn[i][j];mn[i][j] = -1;//禁止走回头路dfs(mn,m,n,i-1,j,min,li);//向上dfs(mn,m,n,i+1,j,min,li);//向下dfs(mn,m,n,i,j-1,min,li);//向左dfs(mn,m,n,i,j+1,min,li);//向右mn[i][j] = temp;//回溯		}}

#案例2-可以组成网络的服务器

在一个机房中,服务器的位置标识在n*m的整数矩阵网格中,1表示单元格上有服务器,0表示没有。如果两台服务器位于同一行或者同一列中紧邻的位置,则认为它们之间可以组成一个局域网,请你统计机房中最大的局域网包含的服务器个数。

输入描述

第一行输入两个正整数,n和m,0<n,m<=100

之后为n*m的二维数组,代表服务器信息

输出描述

最大局域网包含的服务器个数。

示例1

输入:
2 2
1 0
1 1输出:
3说明: [0][0]、[1][0]、[1][1] 三台服务器互相连接,可以组成局域网。 

代码:

思路:

1)上下左右搜索,被搜索到的位置更新为0。

2)该题也可以使用并查集实现。【代码附后方】

package algorithm.huawei;import java.util.Scanner;
/*案例:
3 6
1 0 1 1 0 1
1 1 1 0 0 1
1 0 1 1 0 1
9*/
/*
3 6
1 0 1 1 1 0
1 1 1 0 0 1
1 0 1 1 0 1
10*/
public class Test24Tu {public static void main(String[] args) {Scanner in = new Scanner(System.in);while (in.hasNextInt()) {int n = in.nextInt();int m = in.nextInt();in.nextLine();int[][] mn = new int[n][m];for(int i=0;i<n;i++){for(int j=0;j<m;j++){mn[i][j] = in.nextInt();}in.nextLine();}int max=0;for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(mn[i][j]==0){continue;}max = Math.max(max, dfs(mn,m,n,i,j));}}System.out.println(max);}}private static int dfs(int[][] mn, int m, int n, int x, int y) {if(x<0 || y<0 || x>=n || y>=m || mn[x][y]==0){return 0;}int cnt=0;if(mn[x][y]==1){cnt=1;mn[x][y]=0;}int up=dfs(mn,m,n,x-1,y);//向上int down=dfs(mn,m,n,x+1,y);//向下int left=dfs(mn,m,n,x,y-1);//向左int right=dfs(mn,m,n,x,y+1);//向右return up+down+left+right+cnt;}}
package algorithm.huawei;import java.util.Arrays;
import java.util.Scanner;
/*案例:
3 6
1 0 1 1 0 1
1 1 1 0 0 1
1 0 1 1 0 1
9*/
/*
3 6
1 0 1 1 1 0
1 1 1 0 0 1
1 0 1 1 0 1
10*/
public class Test24Tu {public static void main(String[] args) {Scanner in = new Scanner(System.in);while (in.hasNextInt()) {int n = in.nextInt();int m = in.nextInt();in.nextLine();int[][] mn = new int[n][m];for(int i=0;i<n;i++){for(int j=0;j<m;j++){mn[i][j] = in.nextInt();}in.nextLine();}
//================方案1:递归求解====================//	/*int max=0;for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(mn[i][j]==0){continue;}max = Math.max(max, dfs(mn,m,n,i,j));}}System.out.println(max);*///================方案2:并查集求解====================//			int[] us = new int[n*m];Arrays.fill(us, -1);for(int i=0;i<n;i++){for(int j=0;j<m;j++){int index=i*m+j;//数组下标if(mn[i][j]==1){boolean left = (j-1>=0 && mn[i][j-1]==1);//左侧是否有1boolean up = (i-1>=0 && mn[i-1][j]==1);//上侧是否有1if(left && up){//如果都有则进行合并,将上边并查集合到左边//找到左侧的根int rootL = findRoot(us,index-1);//找到上侧的根int rootU = findRoot(us,(i-1)*m+j);us[rootL]=us[rootL]+us[rootU]-1;us[rootU]=rootL;us[index] = rootL;}else if(left){//只有左侧有则合并到左侧//找到左侧的根int root = findRoot(us,index-1);us[root]-=1;us[index] = root;}else if(up){//只有上侧有则合并到上侧//找到上侧的根int root = findRoot(us,(i-1)*m+j);us[root]-=1;us[index] = root;}else{//都没有则自己是新并查集的根us[index] = -1;}}}}int min=0;for(int i=0;i<us.length;i++){if(us[i]<0){min = Math.min(min, us[i]);}}System.out.println(-min);}}private static int findRoot(int[] us, int i) {while(us[i]>=0){i=us[i];}return i;}private static int dfs(int[][] mn, int m, int n, int x, int y) {if(x<0 || y<0 || x>=n || y>=m || mn[x][y]==0){return 0;}int cnt=0;if(mn[x][y]==1){cnt=1;mn[x][y]=0;}int up=dfs(mn,m,n,x-1,y);//向上int down=dfs(mn,m,n,x+1,y);//向下int left=dfs(mn,m,n,x,y-1);//向左int right=dfs(mn,m,n,x,y+1);//向右return up+down+left+right+cnt;}}

2、最长子串

滑动窗口、状态打标

#案例1-出现偶数次最长子字符串的长度

题目描述

给你一个字符串 s,字符串 s 首尾相连成一个环形,请你在环中找出 'l'、'o'、'x' 字符都恰好出现了偶数次最长子字符串的长度。

输入描述

输入是一串小写的字母组成的字符串

输出描述

输出是一个整数

1 ≤ s.length ≤ 5 * 10^5

s只包含小写英文字母

代码:

package algorithm.huawei;import java.util.Scanner;//思路
//经典的状态压缩动态规划, 一般遇到要保存的状态不多的问题时都可以通过状态压缩来解决
//注意到元音字母只有 5 个, 所以根据不同字母的奇偶性总共也就 32 个状态
//状态为 0 时代表[0,0,0,0,0], 表示所有元音字母都有偶数个
//状态为 1 时代表[0,0,0,0,1], 表示只有 a 是奇数, 其余字母有偶数个
//状态为 2 时代表[0,0,0,1,0], 表示只有 e 是奇数, 其余字母有偶数个
//...
//状态为 31 时代表[1,1,1,1,1], 表示所有元音字母都有奇数个
//可以利用这一点, 存不同状态下的最左边下标, 并保存当前的状态, 初始化状态为 0, 因为此时各个元音字母都是 0 个, 即偶数个
//如果当前下标 i 对应的状态已经有最左下标 j 了, 那么[j+1,i]这段区间的各个元音字母的数目一定是偶数个, 这样才能保证 i 和 j 处的状态相同, 如果其长度大于结果值就更新结果即可
//特别注意当状态为 0 时本身就是合法的, 长度就是当前下标+1, 所以可以初始化该状态的下标为-1, 这样就可以和其他状态下的逻辑一致了
//
public class Test12ZichuanChangdu {public static void main(String[] args) {Scanner sc = new Scanner(System.in);String input = sc.nextLine();System.out.println(getResult(input));}public static int getResult(String s) {int index = 0b000;
//    	每个下标代表一个状态,值代表符合该状态的第一个元素的下标int[] status = new int[8];status[0]=-1;int maxLen = 0;for (int i = 0; i < s.length() * 2; i++) {char c = s.charAt(i % s.length());switch (c) {case 'l':index ^= 0b100;break;case 'o':index ^= 0b010;break;case 'x':index ^= 0b001;break;}if (status[index] == 0) {status[index] = i;}else{maxLen = Math.max(maxLen, i-status[index]<=s.length()?i-status[index]:maxLen);}}return maxLen;}}

3、最长公共子串

动态规划

4、最长序列

线段树

5、四则运算

6、进出问题

通用思路

队列、栈、双端队列

#案例1-篮球游戏

幼儿园里有一个放倒的圆桶,它是一个线性结构,允许在桶的右边将篮球放入,可以在桶的左边和右边将篮球取出。

每个篮球有单独的编号,老师可以连续放入 一个或多个篮球,小朋友可以在桶左边或右边将篮球取出,当桶里只有一个篮球的情况下,必须从左边取出。

如老师按顺序放入1、2、3、4、5 共5个编号的篮球,那么小朋友可以依次取出的编号为“1,2,3,4,5”或者“3,1,2,4,5”编号的篮球,无法取出 “5,1,3,2,4” 编号的篮球。

其中“3,1,2,4,5”的取出场景为:

  • 连续放入1,2,3号

  • 从右边取出3号

  • 从左边取出1号

  • 从左边取出2号

  • 放入4号

  • 从左边取出4号

  • 放入5号

  • 从左边取出5号

简单起见,我们以L表示左,R表示右,此时的篮球的依次取出序列为“ RLLLL ”

输入描述

1、第一行的数字作为老师依次放入的篮球编号;

2、第二行的数字作为要检查是否能够按照放入顺序取出的篮球编号;

其中篮球编号用逗号进行分隔。

输出描述

对于每个篮球的取出序列,如果确实可以获取,请打印出其按照左右方向的操作的取出顺序,如果无法获取则打印"NO" 。

补充说明:

  • 1<=篮球的编号,篮球个数<=200;

  • 篮球上的数字不重复;

  • 输出的结果中LR的必须为大写;

示例1

输入:
4,5,6,7,0,1,2
6,4,0,1,2,5,7输出:
RLRRRLL说明:
篮球的取出顺序依次为 “右,左,右,右,右,左,左”

示例2

输入:
4,5,6,7,0,1,2
6,0,5,1,2,4,7输出:
NO说明:
无法取出对应序列的篮球

示例3

输入:
1,2,3,4
1,2,3,5输出:
NO说明:
不存在编号为5的篮球,所以无法取出对应的编号数据

代码:

package algorithm.huawei;import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;public class Test126 {public static void main(String[] args) {Scanner in = new Scanner(System.in);while (in.hasNextLine()) {String[] sa = in.nextLine().split(",");Deque<Integer> que = new ArrayDeque<Integer>();for(int i=0;i<sa.length;i++){que.offer(Integer.parseInt(sa[i]));}String[] sa2 = in.nextLine().split(",");List<Integer> take = new ArrayList<Integer>();for(int i=0;i<sa2.length;i++){take.add(Integer.parseInt(sa2[i]));}LinkedList<Integer> ll = new LinkedList<Integer>();int takeIndex = 0;StringBuilder sb = new StringBuilder();while(!que.isEmpty() || ll.size()>0){while(que.size()>0 && (ll==null || !ll.contains(take.get(takeIndex)))){ll.add(que.poll());}if(ll.peekFirst()==take.get(takeIndex)){sb.append("L");ll.pollFirst();}else if(ll.peekLast()==take.get(takeIndex)){sb.append("R");ll.pollLast();}else{sb=new StringBuilder("NO");break;}takeIndex++;}System.out.println(sb.toString());}}}

#案例2-火车进出站

给定一个正整数N代表火车数量,0<N<10,接下来输入火车入站的序列,一共N辆火车,每辆火车以数字1-9编号,火车站只有一个方向进出,同时停靠在火车站的列车中,只有后进站的出站了,先进站的才能出站。

要求输出所有火车出站的方案,以字典序排序输出。

数据范围:1≤n≤10 

进阶:时间复杂度:O(n!) ,空间复杂度:O(n) 

输入描述:

第一行输入一个正整数N(0 < N <= 10),第二行包括N个正整数,范围为1到10。

输出描述:

输出以字典序从小到大排序的火车出站序列号,每个编号以空格隔开,每个输出序列换行,具体见sample。

示例1

输入:

3
1 2 3

复制输出:

1 2 3
1 3 2
2 1 3
2 3 1
3 2 1

复制说明:

第一种方案:1进、1出、2进、2出、3进、3出
第二种方案:1进、1出、2进、3进、3出、2出
第三种方案:1进、2进、2出、1出、3进、3出
第四种方案:1进、2进、2出、3进、3出、1出
第五种方案:1进、2进、3进、3出、2出、1出
请注意,[3,1,2]这个序列是不可能实现的。  

代码:

import java.util.*;
// 队列表示未进站的火车
// 栈表示已进站的火车
// 每次火车进站后有两种选择:1.直接出站 2.等待下列火车进站  使用递归考虑
// 记录和打印的递归函数往往是void,如果递归完成后还存在后续逻辑,一般情况下当前输入变量不应受到递归的影响(所以当函数参数为引用类型时,递归的参数应当重新new出来或者深拷贝出来)
public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);while (sc.hasNext()) {int n = sc.nextInt();// 未进站的火车Queue<Integer> queue = new LinkedList<>();// 已进站的火车Stack<Integer> stack = new Stack<>();for (int i = 0; i < n; i++) {queue.offer(sc.nextInt());}List<String> outQueueList = new ArrayList<>();// 获取所有出站队列保存到outQueueListprocessOutQueue(queue, stack, "", outQueueList);// 排序Collections.sort(outQueueList);for (String str : outQueueList) {System.out.println(str);}}}private static void processOutQueue(Queue<Integer> queue, Stack<Integer> stack,String outQueue, List<String> outQueueList) {// 如果队列和栈都为空,则保存出站信息if (queue.isEmpty() && stack.isEmpty()) {outQueueList.add(outQueue.trim());return;}// 二:进栈if (!queue.isEmpty()) {// 先克隆,这里全部克隆的原因是因为递归完回来后,不能影响我的第二种选择// processOutQueue前面的逻辑,递归越深的越晚执行;processOutQueue后面的代码(下方的出栈代码)递归越深的越先执行Queue<Integer> tempQueue = new LinkedList<>(queue);Stack<Integer> tempStack = (Stack<Integer>) stack.clone();tempStack.push(tempQueue.poll());processOutQueue(tempQueue, tempStack, outQueue, outQueueList);}// 队列和栈有两种情况:出栈或进栈// 一:出栈if (!stack.isEmpty()) {// 先克隆Queue<Integer> tempQueue = new LinkedList<>(queue);Stack<Integer> tempStack = (Stack<Integer>) stack.clone();String tempOutQueue = outQueue + (tempStack.pop() + " ");processOutQueue(tempQueue, tempStack, tempOutQueue, outQueueList);}}
}

7、最大匹配数问题

通用思路

匈牙利匹配算法(先到先得,能让则让)

#案例1-素数伴侣

题目描述
若两个正整数的和为素数,则这两个正整数称之为“素数伴侣”,如2和5、6和13,它们能应用于通信加密。现在密码学会请你设计一个程序,从已有的 N ( N 为偶数)个正整数中挑选出若干对组成“素数伴侣”,挑选方案多种多样,例如有4个正整数:2,5,6,13,如果将5和6分为一组中只能得到一组“素数伴侣”,而将2和5、6和13编组将得到两组“素数伴侣”,能组成“素数伴侣”最多的方案称为“最佳方案”,当然密码学会希望你寻找出“最佳方案”。

输入:

有一个正偶数 n ,表示待挑选的自然数的个数。后面给出 n 个具体的数字。

输出:

输出一个整数 K ,表示你求得的“最佳方案”组成“素数伴侣”的对数。

数据范围: 1≤n≤100  ,输入的数据大小满足 2≤val≤30000 

输入描述:

输入说明
1 输入一个正偶数 n
2 输入 n 个整数

输出描述:

求得的“最佳方案”组成“素数伴侣”的对数。

示例1

输入:

4
2 5 6 13

复制输出:

2

复制

示例2

输入:

2
3 6

复制输出:

0

代码:

import java.util.*;// 注意类名必须为 Main, 不要有任何 package xxx 信息
// 遇到递归出现在循环里面的,终止条件则是想办法让越深层的递归循环次数越少,直到一次循环条件都不满足则返回默认的值
public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextInt()) { // 注意 while 处理多个 caseint n = in.nextInt();in.nextLine();// 奇数数组List<Integer> odds = new ArrayList<Integer>();// 偶数数组List<Integer> events = new ArrayList<Integer>();for(int i=0;i<n;i++){int var = in.nextInt();if(var%2 == 0){events.add(var);}else{odds.add(var);}}int count = 0;int[] ifMatch = new int[events.size()];for(int i=0;i<odds.size();i++){boolean[] canuse = new boolean[events.size()];Arrays.fill(canuse,true);if(dfs(odds.get(i),events,ifMatch,canuse)){count++;};}System.out.println(count);}}public static boolean dfs(int x,List<Integer> events,int[] ifMatch,boolean[] canuse) {for(int i=0;i<events.size();i++){// 先到先得:如果该位置能用且符合素数且该位置没被占用则可以占用if(canuse[i] && isPrime(x+events.get(i))){canuse[i] = false;//把位置改为不可用if(ifMatch[i]==0 || dfs(ifMatch[i],events,ifMatch,canuse)){//如果该位置没被占用,或者被占用了但是占用的odd能重新找到其他event进行匹配,则可以使用ifMatch[i] = x;return true;}}}return false;}public static boolean isPrime(int x) {for(int i=2;i<=Math.sqrt(x);i++){if(x%i==0){return false;}}return true;}
}

#案例2-矩阵匹配

题目描述

从一个 N * M(N ≤ M)的矩阵中选出 N 个数,任意两个数字不能在同一行或同一列,求选出来的 N 个数中第 K 大的数字的最小值是多少。

输入描述

输入矩阵要求:1 ≤ K ≤ N ≤ M ≤ 150

输入格式:

N M K

N*M矩阵

输出描述

N*M 的矩阵中可以选出 M! / N! 种组合数组,每个组合数组种第 K 大的数中的最小值。无需考虑重复数字,直接取字典排序结果即可。

备注

注意:结果是第 K 大的数字的最小值

代码:

思路:每一个行号只能跟一个列号匹配,我们可以利用二分法枚举第k大的值,然后通过匈牙利算法检查符合条件的且小于这个值的匹配数量是否满足要求,如果满足则说明枚举值kth给大了,如果不满足说明枚举值kth给小了。

import java.util.Arrays;
import java.util.Scanner;public class Main {static int n;static int m;static int k;static int[][] matrix;public static void main(String[] args) {Scanner sc = new Scanner(System.in);n = sc.nextInt();m = sc.nextInt();k = sc.nextInt();int min = 1;int max = Integer.MIN_VALUE;matrix = new int[n][m];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {matrix[i][j] = sc.nextInt();max = Math.max(max, matrix[i][j]);}}// 二分枚举第K大值while (min <= max) {// mid就是被枚举出来的N个数中的第K大值int mid = (min + max) >> 1;// 检查mid作为N个数中第K大值时,是否存在N-K+1个不大于它的值if (check(mid)) {max = mid - 1;} else {min = mid + 1;}}System.out.println(min);}public static boolean check(int kth) {// 利用二分图最大匹配来求解,小于等于kth(第K大值)的元素个数(即二分图最大匹配)int smallerCount = 0;// 记录每个列号的匹配成功的行号int[] match = new int[m];// 初始时每个列号都处于未配对状态,此时将列号配对的行号赋值为-1Arrays.fill(match, -1);// 遍历行号,每个行号对互相心仪的列号发起配对请求for (int i = 0; i < n; i++) {// 记录增广路访问过的列号boolean[] vis = new boolean[m];if (dfs(i, kth, match, vis)) smallerCount++;}return smallerCount >= n - k + 1;}public static boolean dfs(int i, int kth, int[] match, boolean[] vis) {// 行号 i 发起了配对请求// 遍历每一个列号jfor (int j = 0; j < m; j++) {// 如果当前列号j未被增广路探索过 && 当前列j行i可以配对(如果行列号位置(i,j)对应矩阵元素值小于等于kth(第K大值),则可以配对)if (!vis[j] && matrix[i][j] <= kth) {vis[j] = true;// 如果对应列号j未配对,或者,已配对但是配对的行号match[j]可以找到其他列号重新配对if (match[j] == -1 || dfs(match[j], kth, match, vis)) {// 则当前行号i 和 列号j 可以配对match[j] = i;return true;}}}return false;}
}

本案例参考&鸣谢:

华为OD机试 - 矩阵匹配(Java & JS & Python & C & C++)_od 矩阵匹配-CSDN博客

8、分配方案的最大效益问题

通用思路:

1)PriorityQueue:堆的使用。

2)动态规划:不关心具体方案,只关心最值情况优先考虑动态规划的可能。

#案例1-贪心歌手

一个歌手准备从A城去B城参加演出

  1. 按照合同,他必须在T天内赶到
  2. 歌手不能往回走
  3. 每两座城市之间需要的天数都可以提前获知。
  4. 歌手在每座城市都可以在路边卖唱赚钱。经过调研,歌手提前获知了每座城市卖唱的收入预期: 如果在一座城市第一天卖唱可以赚M,后续每天的收入会减少D(第二天赚的钱是M - D,第三天是M-2D…)如果收入减到0就不会再少了。
  5. 歌手到达后的第二天才能开始卖唱。如果今天卖过唱,第二天才能出发

贪心的歌手最多可以赚多少钱?

输入描述

第一行两个数字 TN,中间用空格隔开 T 代表总天数; N 代表路上经过N座城市; 0 < T < 1000 ,0 < N < 100

第二行N+1个数字,中间用空格隔开 代表每两座城市之间耗费的时间。 其总和<=T

接下来N行,每行两个数字MD,中间用空格隔开.

代表每个城市的收入预期。

0< M <1000, 0 < D < 100

输出描述

一个数字。代表歌手最多可以赚多少钱。以回车结束

示例1

输入:
10 2
1 1 2
120 20
90 10输出:
540说明:
总共10天,路上经过2座城市。 路上共花1+1+2=4天 剩余6天最好的计划是
在第一座城市待3天,在第二座城市待3天 在第一座城市赚的钱:120+100+80=300 
在第二座城市赚的钱:90+80+70=240 
一共300+240 = 540

代码:

思路:

1)每次都待预期收入最高的城市,待完更新该城市的最新预期。

2)数据结构堆的使用,每次放入数据都会按比较器定义的大小顺序进行放入。

package algorithm.huawei;import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Scanner;public class Test82 {public static void main(String[] args) {Scanner in = new Scanner(System.in);while (in.hasNextInt()) {int t = in.nextInt();//t天int n = in.nextInt();//n个城市in.nextLine();int route = 0;//路上耗时for(int i=0;i<n+1;i++){route+=in.nextInt();}in.nextLine();City[] citys = new City[n];PriorityQueue<City> pq = new PriorityQueue<City>((c1,c2)->c2.fee-c1.fee);for(int i=0;i<n;i++){int fee=in.nextInt();int q=in.nextInt();City city = new City(fee,q);pq.add(city);in.nextLine();}
//			Arrays.sort(citys,(c1,c2)->c2.fee-c1.fee);int max=0;int i=0;int k=0;//当前城市待的天数int lest = t-route;//剩余天数while(lest>0){lest--;City city = pq.poll();int fee=city.fee;int q=city.q;max+=fee;city.fee=fee-q;pq.add(city);}System.out.println(max);}}}class City{int fee;int q;public City(int fee, int q) {super();this.fee = fee;this.q = q;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/41972.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

12种增强Python代码的函数式编程技术

前言 什么是函数式编程&#xff1f; 一句话总结&#xff1a;函数式编程(functional programming)是一种编程范式&#xff0c;之外还有面向对象&#xff08;OOP&#xff09;、面向过程、逻辑式编程等。 函数式编程是一种高度抽象的编程范式&#xff0c;它倡导使用纯函数&#x…

Docker-11☆ Docker Compose部署RuoYi-Cloud

一、环境准备 1.安装Docker 附:Docker-02-01☆ Docker在线下载安装与配置(linux) 2.安装Docker Compose 附:Docker-10☆ Docker Compose 二、源码下载 若依官网:RuoYi 若依官方网站 鼠标放到"源码地址"上,点击"RuoYi-Cloud 微服务版"。 跳转至G…

深入理解计算机系统 CSAPP 家庭作业8.22

书本知识够你写出答案,但是如果你想验证你写的答案,就要一些额外的东西.这本书很多题目都是如此 /** mysystem.c*/ #include <stdio.h> #include "csapp.h"int mysystem(char* command) {pid_t pid;int status;if ((pid Fork()) 0) {/*这里是关键用子程序去…

新加坡工作和生活指北:工作篇

文章首发于公众号&#xff1a;Keegan小钢 一年多以前&#xff08;2022 年 8 月初&#xff09;&#xff0c;那时我过来新加坡才 4 个多月&#xff0c;就写了篇文章分享了当时在新加坡的生活和工作体验。文章得到的反响不错&#xff0c;但也反馈出了一些新的问题&#xff0c;比如…

预训练对齐:数学理论到工程实践的桥梁

在人工智能和机器学习领域&#xff0c;预训练模型的对齐是一个至关重要的概念。本篇博客源自听了一场黄民烈老师关于大模型对齐的分享&#xff0c;整理内容如下&#xff0c;供大家参考。 数学理论中的预训练对齐 数学理论上&#xff0c;预训练对齐是什么&#xff1f; 序列…

Keepalived+HAProxy 集群及虚IP切换实践

1、软件介绍 ①Keepalived keepalive是一个用c语言编写的路由软件&#xff0c;这个项目的主要目标是为Linux系统和基于Linux的基础设施提供简单而健壮的负载平衡和高可用性设施。负载均衡框架依赖于众所周知且广泛使用的Linux Virtual Server (IPVS)内核模块提供第4层负载均衡…

srs直播内网拉流带宽飙升问题记录

问题背景 srs部署在云服务器上&#xff0c;32核cpu&#xff0c;64G内存&#xff0c;带宽300M. 客户端从srs拉流&#xff0c;发现外网客户端拉流&#xff0c;cpu和带宽都正常。然而内网客户端拉流&#xff0c;拉流人数超过5人以上&#xff0c;带宽就会迅速飙升。 排查 用srs…

数学建模论文写作文档word

目录 1. 摘要写法1.1 确定题目与方法1.2 编写开头段落1.3 填写问题一1.4 重复步骤3填写其他问题1.5 编写结尾段落1.6 编写关键词 2. 问题重述2.1 问题背景2.2 问题提出 3. 问题分析4. 问题X模型的建立与求解5. 模型的分析5.1 灵敏度分析5.2 误差分析&#xff08;主要用于预测类…

Milvus lite start 及存储策略

背景 今天开始写下Milvus&#xff0c;为了方便&#xff0c;我直接使用的是 milvus-lite 版本&#xff0c;default 情况下&#xff0c;你可能不知道他到底将 db 存储到什么位置了。启动 default-server&#xff0c;看下Milvus 的start及存储逻辑 主逻辑 def start(self):sel…

【绿色版】Mysql下载、安装、配置与使用(保姆级教程)

大家都知道&#xff0c;Mysql安装版的卸载过程非常繁琐&#xff0c;而且卸载不干净会出现许多问题&#xff0c;很容易让大家陷入重装系统的窘境。基于此&#xff0c;博主今天给大家分享绿色版Mysql的安装、配置与使用。 目录 一、Mysql安装、配置与使用 1、下载解压 2、创建…

vue对axios进行请求响应封装

一、原因 像是在一些业务逻辑上&#xff0c;比如需要在请求之前展示loading效果&#xff0c;或者在登录的时候判断身份信息&#xff08;token&#xff09;等信息有没有过期&#xff0c;再者根据服务器响应回来的code码进行相应的提示信息。等等在请求之前&#xff0c;之后做的一…

ABAP注释快捷键修改(留着备用)

ABAP注释快捷键修改(留着备用) 在使用ABAP编辑器的时候&#xff0c;原有的添加代码注释和取消代码注释的快捷键未生效&#xff0c;这时我们可以考虑对注释快捷键进行修改 在事务码SE38(ABAP编辑器)屏幕右下角&#xff0c;点击【Options选项】图标 在【键盘】|【命令】输入栏中…

DWM 相关实现代码 [自用]

1. DWM 缩略图和模糊隐藏实现半透明 #include <windows.h> #include <dwmapi.h> #include <string> #pragma comment(lib, "dwmapi.lib")// 检查 UWP 窗口是否可见 bool IsUWPWindowVisible(HWND hwnd) {DWORD cloaked 0;DwmGetWindowAttribute(…

【c语言】玩转文件操作

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C语言 目录 引言 一、文件的打开和关闭 1.流 2.标准流 3.文本文件和二进制文件 4.控制文件打开与关闭的函数 二、文件的顺序读写 三、文件的随机读写 1…

深入理解OAuth 2.0:原理、流程与实践

一、什么是OAuth 2.0 1. 什么是OAuth 2.0 OAuth 2.0 是一套关于授权的行业标准协议。 OAuth 2.0 允许用户授权第三方应用访问他们在另一个服务提供方上的数据&#xff0c;而无需分享他们的凭据&#xff08;如用户名、密码&#xff09;。 2. OAuth 2.0 应用场景 OAuth 2.0的…

服务器U盘安装Centos 7时提示Warning:/dev/root does not exist

这是没有找到正确的镜像路径导致的&#xff0c;我们可以在命令行输入ls /dev看一下有哪些盘符 像图中红色圈起来的就是我插入U盘的盘符&#xff0c;大家的输几盘可能做了多个逻辑盘&#xff0c;这种情况下就可以先将U盘拔掉再ls /dev看一下和刚才相比少了那两个盘符&#xff0c…

权力之望怎么下载客户端 权力之望一键下载

《权力之望》是一款由NX3 Games开发、Smilegate发行的多人在线动作MMORPG游戏。这款游戏最大的特点是高度的自由度和丰富的角色定制选项。我们在游戏中不仅可以自由更换武器&#xff0c;而且游戏还提供了54种能力和60多种职业选择&#xff0c;让我们可以根据自己的游戏风格和喜…

继 承

为什么要有继承&#xff0c;继承的作用&#xff1f; 继承(inheritance)机制&#xff1a;是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加新功能&#xff0c;这样产生新的类&#xff0c;称派生类。 …

【人工智能】—基于成都市各区(市)县租房价格预测建模研究

引言 随着城市化进程的加速&#xff0c;人口流动日益频繁&#xff0c;租房市场作为城市生活的重要组成部分&#xff0c;其价格波动对居民生活质量和城市经济发展具有显著影响。成都市&#xff0c;作为中国西部地区的经济、文化、交通和科技中心&#xff0c;近年来吸引了大量人…

为什么独立站需要高质量的GPB外链?

独立站需要高质量的GPB外链&#xff0c;主要是因为它们能显著提升网站的可信度和可见性。高质量的外链相当于得到其他权威网站的认可和推荐&#xff0c;这会让搜索引擎认为你的内容有价值&#xff0c;从而提升你的搜索排名。试想一下&#xff0c;当其他有影响力的网站愿意链接到…