最长公共子序列
package 算法设计与分析和蓝桥杯; import java.util.Arrays; import java.util.Scanner; /* 动态规划: 最长公共子序列:给予两个序列,求出两个序列按次序的共有子序列。 如:abcdfwwz和alcqdlw的公共子序列是acdw。解题思路是使用动态规划的思想,求大序列的公共子序列可以转为小序列的公共序列,进而知道大序列的 公共子序列。 递推矩阵strAB[i][j]递推公式为 (1) 0 if i=0或j=0 (2) str[i-1][j-1]+1 若i,j>0 strA.charAt(i - 1) == strB.charAt(j - 1) (3) max(str[i][j-1]+1,str[i-1][j]+1) 若i,j>0 strA.charAt(i - 1) != strB.charAt(j - 1) */ public class MaxSequeeze { public void getMaxSqueeze(String strA, String strB) { String common = ""; int strAB[][] = new int[strA.length() + 1][strB.length() + 1]; for (int i = 0; i < strB.length() + 1; i++) { //公式一 strAB[0][i] = 0; } for (int i = 0; i < strA.length() + 1; i++) { strAB[i][0] = 0; } int indexJ = 1; for (int i = 1; i < strA.length() + 1; i++) { for (int j = indexJ; j < strB.length() + 1; j++) { if (strA.charAt(i - 1) == strB.charAt(j - 1)) { //公式二, strAB[i][j] = strAB[i - 1][j - 1] + 1; for (int k = j + 1; k < strB.length() + 1; k++) { strAB[i][k] = strAB[i][j]; } break; } else { strAB[i][j] = Math.max(strAB[i - 1][j], strAB[i][j - 1]); //公式三 } } } int indexA = strA.length(); while (true) { if (indexA <= 0) break; for (int i = strB.length(); i > 0; i--) { if (strAB[indexA][i] == strAB[indexA - 1][i - 1] + 1 && strAB[indexA][i] == strAB[indexA - 1][i] + 1 && strAB[indexA][i] == strAB[indexA][i - 1] + 1) { //对于最长公共序列的某个公共值,一定满足strAB[i][j]比strAB[i-1][j]和strAB[i][j-1]和str[i-1][j-1]大1 //此时该位置说明是公共序列元素位置 common = strA.charAt(indexA-1) + common; break; } } indexA --; } System.out.println("最长公共子序列的长度为" + strAB[strA.length()][strB.length()]); System.out.println("最长公共子序列为" + common); } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String strA = scanner.next(); String strB = scanner.next(); MaxSequeeze maxSequeeze = new MaxSequeeze(); maxSequeeze.getMaxSqueeze(strA, strB); } } /* abcdefghijklmn abdfrewkasd 最长公共子序列的长度为5 最长公共子序列为abdefk */
批处理作业调度_回溯法_排列树
https://www.cnblogs.com/henuliulei/p/10196118.html
package 算法设计与分析和蓝桥杯; import 小灰灰.Perm; import java.util.Arrays; import java.util.Scanner; /* 批处理作业调度问题 给定n个作业的集合J={J1,J2,…,Jn}。每一个作业有两项任务分别在两台机器上完成。每个作业必须先由机器1处理,再由机器2处理。作业Ji需要机器j的处理时间为tji,i=1,2,…n,j=1,2。对于一个确定的作业调度,设Fji是作业i在机器j上完成处理的时间。则所有作业在机器2上完成处理的时间和f=F21+F22+…+F2n称为该作业调度的完成时间和。 批处理作业调度问题要求,对于给定的n个作业,制定最佳的作业调度方案,使其完成时间和最小。 样例输入 3 2 1 3 1 2 3 样例输出 18 1 3 2 */ public class batchWork { static int minValue = Integer.MAX_VALUE; void dfs(int level, int num, int work[][], int perm[], int best[]) { if (level >= num) { int machineA[][] = new int[num][2]; //每个作业在A机器上的工作开始时间和结束时间 int machineB[][] = new int[num][2]; //每个工作在B机器上的工作开始时间和结束时间 int timeA = 0; //记录机器A已经完成的作业后的时间 int timeB = 0; //记录机器B已经完成的作业后的时间 for (int i = 0; i < num; i++) { //根据调度方案计算在机器A上的各个作业的开始和结束时间安排 machineA[perm[i]][0] = timeA; machineA[perm[i]][1] = timeA + work[perm[i]][0]; timeA = machineA[perm[i]][1]; } int allTime = 0; //作业调度的完成时间和 for (int i = 0; i < num; i++) { //根据调度方案计算在机器B上的各个作业的开始和结束时间安排 machineB[perm[i]][0] = Math.max(machineA[perm[i]][1], timeB); machineB[perm[i]][1] = Math.max(machineA[perm[i]][1], timeB) + work[perm[i]][1]; timeB = machineB[perm[i]][1]; allTime += timeB; } if (minValue > allTime) { //最佳方案 for (int i = 0; i < num; i++) { best[i] = perm[i]; } minValue = allTime; } } for (int i = level; i < num; i++) { //常规的全排列代码,也说明这是一个排列树 int temp = perm[level]; perm[level] = perm[i]; perm[i] = temp; dfs(level + 1, num, work, perm, best); temp = perm[level]; perm[level] = perm[i]; perm[i] = temp; } } public static void main(String[] args) { int num; Scanner scanner = new Scanner(System.in); num = scanner.nextInt(); int work[][] = new int[num][2]; for (int j = 0; j < num; j++) { work[j][0] = scanner.nextInt(); //在A机器上的工作时间 work[j][1] = scanner.nextInt(); //在B机器上的工作时间 } int perm[] = new int[num]; //各个作业的一种排序结果,其实就是存储对作业进行调度的每一种方案 int best[] = new int[num]; //存储最佳调度方案 for (int i = 0; i < num; i++) { perm[i] = i; } batchWork batchWork = new batchWork(); batchWork.dfs(0, num, work, perm, best); System.out.println("合理的順序是" + Arrays.toString(best)); System.out.println("最短時間" + minValue); } }
多级调度问题
package 算法设计与分析和蓝桥杯; import java.util.Arrays; import java.util.Scanner; /** * 多级调度问题,贪心思想,保证各个机器分配的作业时间最够平均来达到时间最短 * 问题描述: * 设有n个独立的作业{1, 2, …, n}, 由m台相同的机器进行加工处理. 作业i所需时间为t i. 约定:任何作业可以在任何一台机器上加工处理, 但未完工前不允许中断处理,任何作业不能拆分成更小的子作业。要求给出一种作业调度方案,使所给的n 个作业在尽可能短的时间内由m台机器加工处理完成。 * <p> * 问题分析: * 当作业n的数量小于机器的数量m的时,只需要作业一一分配到每一台机器中,只要把机器i的[0,ti]时间区间分配给作业i即可,所需要的时间便是max[ti]。 * 当作业n的数量大于机器的数量m的时,应使所有机器尽可能忙碌,首先将n个作业依其所需的处理时间从大到小排序。然后以此顺序将作业分配给空闲的处理机。 * 假定有7个独立作业,所需处理时间分别为{2,14,4,16,6,5,3},由三台机器M1,M2,M3加工。按照贪心算法产生的作业调度,所需总加工时间为17. */ public class ManyMachine { static int getMinindex(int[] machine) { int index = 0; int minValue = Integer.MAX_VALUE; for (int i = 0; i < machine.length; i++) { if(machine[i] < minValue){ minValue = machine[i]; index = i; } } return index; } void greedy(int machineNum, int work[]) { int[] machine = new int[machineNum]; Arrays.sort(work); for (int i = work.length - 1; i >= 0; i--) { int minIndex = ManyMachine.getMinindex(machine); machine[minIndex] += work[i]; } int value = 0; for (int i = 0; i < machineNum; i++) { if(machine[i] >= value){ value = machine[i]; } } System.out.println("调度后所需加工的时间为" + value); } public static void main(String[] args) { int workNum, machineNum; //作业数,机器数 Scanner scanner = new Scanner(System.in); workNum = scanner.nextInt(); machineNum = scanner.nextInt(); int work[] = new int[workNum]; for (int i = 0; i < workNum; i++) { work[i] = scanner.nextInt(); } ManyMachine manyMachine = new ManyMachine(); manyMachine.greedy(machineNum,work); } }
装载问题
子集树的特点是每个元素对应树的一行,1,0分别表示是否选择该元素,通过递归回溯来得到满足条件的结果,注意和排列数的不同(排列数n!,每次有多个元素直到1个,所以根据具体问题判断该问题是子集树还是排列树)
package 算法设计与分析和蓝桥杯; import java.util.Arrays; import java.util.Scanner; /* 子集树,,, 每一个箱子有两个选择,装和不装,所以是个二叉树,只需要深度搜索找出结果就可以 */ public class Driver { int bestResult = Integer.MIN_VALUE; void dfs(int level, int capacity, int[] weight, int x[], int[] best) { if (level >= weight.length) { System.out.println(Arrays.toString(x)); int sum = 0; for (int i = 0; i < weight.length; i++) { sum += x[i] * weight[i]; } if (sum <= capacity && sum > bestResult) { bestResult = sum; System.arraycopy(x, 0, best, 0, best.length); } } else{ for (int j = 0; j < 2; j++) { x[level] = j; dfs(level + 1, capacity, weight, x, best); } } } public static void main(String[] args) { int capacity; int num; Scanner scanner = new Scanner(System.in); capacity = scanner.nextInt(); num = scanner.nextInt(); int[] weight = new int[num]; //箱子的重量 for (int i = 0; i < weight.length; i++) { weight[i] = scanner.nextInt(); } int x[] = new int[num]; //用来记录各个箱子装还是不装 int best[] = new int[num]; //最优方案 Driver driver = new Driver(); driver.dfs(0, capacity, weight, x, best); System.out.println("最优装载方案:" + Arrays.toString(best)); } } /* 80 4 18 7 25 36 */
符号三角形问题
(2条消息) 符号三角形_无限迭代中......-CSDN博客_符号三角形
package 算法设计与分析和蓝桥杯; import base.Prim; import java.util.Arrays; import java.util.Scanner; public class CharacterTriangle { static int sum = 0; void dfs(int level, int num,int[] character){ if(num<=level){ // System.out.println(Arrays.toString(character)); int [][] Array = new int[num][num]; for (int i = 0; i < character.length; i++) { Array[0][i] = character[i]; } int add = 0; int sub = 0; for (int i = 0; i < num; i++) { if(character[i]==0) add++; else sub++; } for (int i = 1; i < character.length; i++) { for (int j = 0; j < character.length-i; j++) { if(Array[i-1][j]==Array[i-1][j+1]){ Array[i][j] = 0; add++; }else{ Array[i][j] = 1; sub++; } } } if(add==sub) sum++; } else{ for (int j = 0; j < 2; j++) { // sum ++; character[level] = j; dfs(level+1,num,character); } } } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int num = scanner.nextInt(); int[] character = new int[num]; CharacterTriangle characterTriangle = new CharacterTriangle(); characterTriangle.dfs(0,num,character); System.out.println(sum); } }
n皇后问题
package 算法设计与分析和蓝桥杯; import java.util.Arrays; import java.util.Scanner; public class NQueen { static int sum = 0; static int ok(int level,int []x){ int ok = 1; for (int i = 0; i < level; i++) { if(x[i]==x[level] || Math.abs(i-level)==Math.abs(x[i]-x[level])){ ok = 0; } } return ok; } void dfs(int level,int x[]){ if(level>=x.length){ // System.out.println(Arrays.toString(x)); sum++; }else{ for (int i = 0; i < x.length; i++) { x[level] = i; if(NQueen.ok(level,x)==1) dfs(level+1,x); } } } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int x[] = new int[n]; Arrays.fill(x,0); NQueen nQueen = new NQueen(); nQueen.dfs(0,x); System.out.println(String.format("共有%d中方案",sum)); } }
0-1背包问题_回溯法
package 算法设计与分析和蓝桥杯; import java.util.Arrays; import java.util.Scanner; public class Packet_01 { int bestw = 0; void dfs(int level, int[] weight, int[] value, int capacity, int x[], int best[], int n, int weightSum) { if (level == n) { int sumValue = 0; for (int i = 0; i < n; i++) { sumValue += x[i] * value[i]; } if (sumValue > bestw) { bestw = sumValue; System.arraycopy(x, 0, best, 0, n); } } else { for (int i = 0; i < 2; i++) { if (weightSum + weight[level] * i <= capacity) { x[level] = i; weightSum += weight[level] * i; dfs(level + 1, weight, value, capacity, x, best, n, weightSum); } } } } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int weight[] = new int[n]; int value[] = new int[n]; int x[] = new int[n]; int xBest[] = new int[n]; for (int i = 0; i < n; i++) { weight[i] = scanner.nextInt(); } for (int i = 0; i < n; i++) { value[i] = scanner.nextInt(); } int capacity = scanner.nextInt(); Packet_01 packet_01 = new Packet_01(); packet_01.dfs(0, weight, value, capacity, x, xBest, n, 0); System.out.println("物品选择决策方案是" + Arrays.toString(xBest)); System.out.println("背包容量有限下,最大价值:" + packet_01.bestw); } } /* 重量:2 2 6 5 4 价值:6 3 5 4 6 背包容量:10 */
图的M着色问题
package 算法设计与分析和蓝桥杯; import java.util.Arrays; import java.util.Scanner; public class Mcolor { static int judge(int level,int x[],int [][]map){ int sameColor=0; //默认周围结点没有相同颜色 for (int i = 0; i < level; i++) { if(map[level+1][i+1]==1){ if(x[i]==x[level]) { sameColor=1; break; } } } return sameColor; } void colorDfs(int level, int[][] map, int n, int m, int[] x) { if(level==n){ System.out.println("满足条件的一种这色方案: " + Arrays.toString(x)); }else{ for (int i = 0; i < m; i++) { x[level] = i+1; if(judge(level,x,map)==0){ colorDfs(level+1,map,n,m,x); } } } } public static void main(String[] args) { int n, m; Scanner scanner = new Scanner(System.in); n = scanner.nextInt(); m = scanner.nextInt(); int[][] map = new int[n + 1][n + 1]; //连接情况 int []x = new int[n]; //着色方案 while (true){ //输入结点连接情况 int i = scanner.nextInt(); if(i==-1) break; int j = scanner.nextInt(); map[i][j] = 1; } Mcolor mcolor = new Mcolor(); mcolor.colorDfs(0,map,n,m,x); } } /* 5 4 1 2 1 3 1 4 2 1 2 3 2 4 2 5 3 1 3 2 3 4 4 1 4 2 4 3 4 5 5 2 5 4 -1 */
连续邮资问题
旅行商问题_排列树
package 算法设计与分析和蓝桥杯; import java.util.Arrays; import java.util.Scanner; public class Market { static int sumPath = Integer.MAX_VALUE;//最短总路径 void merchantDfs(int level, int cityNum, int road[][], int path[],int foot[],int bestPath[]) {//深搜 if(level==cityNum){ System.out.println(Arrays.toString(path)); if(road[path[cityNum-1]][1]>0){ int sum =0; path[level] = 1; for (int i = 0; i < path.length; i++) { if(i==path.length-1){ sum += road[path[i]][1]; }else{ sum += road[path[i]][path[i+1]]; } } if(sum < sumPath){ sumPath = sum; System.arraycopy(path,0,bestPath,0,path.length); } } }else{ for (int i = 1; i <= cityNum; i++) { if(level==0) { //保证第一站一定是城市一 foot[1] = 1; path[0] = 1; merchantDfs(level+1,cityNum,road,path,foot, bestPath); break; }else{ if(road[i][path[level-1]]>0 && foot[i]==0){ foot[i] = 1; path[level] = i; merchantDfs(level+1,cityNum,road,path,foot, bestPath); foot[i] = 0; } } } } } void merchantBfs(int level,int cityNum,int road[][], int path[],int bestPath[]){ //广搜 if(level==cityNum){ System.out.println(Arrays.toString(path)); path[path.length-1] = 1; boolean isConnection = true; for (int i = 0; i <path.length-1; i++) { //判断路径是否是连同的 if(road[path[i]][path[i+1]]==0){ isConnection = false; break; } } if(isConnection==true){ int sum = 0; for (int i = 0; i < path.length-1; i++) { sum += road[path[i]][path[i+1]]; } if(sum< sumPath){ sumPath = sum; System.arraycopy(path,0,bestPath,0,path.length); } } }else{ for (int i = level+1; i <=cityNum ; i++) { if(level==0){ path[level] = 1; merchantBfs(level+1,cityNum,road,path,bestPath); }else{ int temp = path[level]; path[level] = path[i-1]; path[i-1] = temp; merchantBfs(level+1,cityNum,road,path,bestPath); temp = path[level]; path[level] = path[i-1]; path[i-1] = temp; } } } } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int cityNum = scanner.nextInt(); int edge = scanner.nextInt(); //边的个数 int road[][] = new int[cityNum + 1][cityNum+1]; //城市间的连接情况 int path[] = new int[cityNum + 1]; int foot[] = new int[cityNum+1]; //记录该城市是否走过 int bestPath[] = new int[cityNum+1]; Arrays.fill(foot,0); for (int i = 0; i < path.length; i++) { path[i] = i+1; } for (int i = 0; i < road.length; i++) { Arrays.fill(road[i],0); } int begin = 0; int end = 0; int roadLength = 0; for (int i = 0; i < edge; i++) { begin = scanner.nextInt(); end = scanner.nextInt(); roadLength = scanner.nextInt(); road[begin][end] = roadLength; road[end][begin] = roadLength; } Market market = new Market(); // market.merchantDfs(0,cityNum,road,path,foot,bestPath); market.merchantBfs(0,cityNum,road,path,bestPath); System.out.println("最佳路线为" + Arrays.toString(bestPath)); } } /* 4 6 1 2 30 1 3 6 1 4 4 2 3 5 2 4 10 3 4 20 */
单源最短路径_BFS
package 算法设计与分析和蓝桥杯; import java.lang.reflect.Array; import java.util.Arrays; import java.util.LinkedList; import java.util.Scanner; import java.util.concurrent.LinkedBlockingQueue; public class ShortestPath { void bfs(int[][] map, int path[][], int length[]) throws InterruptedException { LinkedBlockingQueue<Integer> nodes = new LinkedBlockingQueue<>(); nodes.put(1); //假设所有的图起始结点为1,子孙结点和右兄弟结点编号要小于本身,按照层次遍历的顺序编号 while (true) { if (nodes.isEmpty()) break; int node = nodes.poll(); for (int i = node + 1; i < map.length; i++) { //子孙结点入栈 if (map[node][i] > 0) nodes.put(i); } length[node] = Integer.MAX_VALUE; for (int i = 1; i < node; i++) { //找到父节点,计算父节点的总路径长度和到自己的长度和最小的结点是那个 if (map[i][node] > 0) { if (length[i] + map[i][node] < length[node]) { length[node] = length[i] + map[i][node]; for (int j = 1; j <= path[i].length; j++) { if (j == 1) { path[node][j] = 1; //第一个结点肯定是起始结点 } else { if (path[i][j] > 0) { //父节点的路径 path[node][j] = path[i][j]; } else { //最后一个结点肯定是自己啊 path[node][j] = node; break; } } } } } } } } public static void main(String[] args) throws InterruptedException { Scanner scanner = new Scanner(System.in); int node = scanner.nextInt(); int edge = scanner.nextInt(); int a[] = new int[10]; int map[][] = new int[node + 1][node + 1]; //图 int begin = 0; int end = 0; for (int i = 0; i < edge; i++) { begin = scanner.nextInt(); end = scanner.nextInt(); int len = scanner.nextInt(); map[begin][end] = len; map[end][begin] = len; } int path[][] = new int[node + 1][node + 1]; //记录每个结点的最短路径 int length[] = new int[node + 1]; //每个结点的最短路径 // Arrays.fill(length,Integer.MAX_VALUE); ShortestPath shortestPath = new ShortestPath(); shortestPath.bfs(map,path,length); for (int i = 1; i <=node; i++) { System.out.println(String.format("结点%d的最短路径的线路是%s",i,Arrays.toString(path[i]))); } } } /* 11 16 1 2 2 1 3 4 1 4 6 2 5 2 2 6 4 2 7 10 3 6 8 4 7 8 5 10 2 5 9 10 6 8 2 7 9 3 7 10 4 8 11 3 9 11 2 10 11 1 */