1 贪心算法 加勒比海盗偷财宝
场景:海盗来到了召唤师峡谷,然后丝血准备逃生。但是仍然贪图财宝。现在时间有限,必须要把容量一定的背包里装下最多的财富。
思路:按照性价比把所有宝藏排序。然后按照性价比的顺序往包里装。
// 包的最大容量
private int MAX_WEIGHT = 120;
// 每个宝藏的重量
private int[] weights = new int[] { 35, 30, 60, 50, 40, 10, 25 };
// 每个宝藏的价值
private int[] values = new int[] { 10, 40, 30, 50, 35, 40, 30 };
public static void main(String[] args) {
GreedyPractice greedyPractice = new GreedyPractice();
greedyPractice.getMaxValue(greedyPractice.MAX_WEIGHT,
greedyPractice.weights, greedyPractice.values);
}
/**
* 获取宝藏的最大价值
*/
public void getMaxValue(int capacity, int[] weight, int[] values) {
int size = weight.length;
// 性价比的下标 按照性价比进行排序后 这个下标将会记录 之前的下标
int[] indexArray = new int[size];
// 性价比
double[] costPerformance = new double[size];
for (int i = 0; i < size; i++) {
costPerformance[i] = (double) values[i] / weights[i];
indexArray[i] = i;
}
// 按照性价比进行排序
for (int i = 0; i < size; i++) {
for (int j = 0; j + 1 < size - i; j++) {
if (costPerformance[j] < costPerformance[j + 1]) {
double temp = costPerformance[j];
costPerformance[j] = costPerformance[j + 1];
costPerformance[j + 1] = temp;
int tempIndex = indexArray[j];
indexArray[j] = indexArray[j+1];
indexArray[j + 1] = tempIndex;
}
}
}
// 按照性价比排序的宝藏的质量和价值
int[] w = new int[size];
int[] v = new int[size];
for (int i = 0; i < size; i++) {
w[i] = weight[indexArray[i]];
v[i] = values[indexArray[i]];
}
//包里装的宝藏
List<Integer> pacageContent = new ArrayList<Integer>();
// 开始遍历所有的宝藏 如果宝藏的质量比包的容量小 就装进去
for (int i = 0; i < size; i++) {
if (w[i] < capacity) {
capacity = capacity - w[i];
pacageContent.add(w[i]);
}
}
for (int a : pacageContent) {
System.out.println(a + "");
}
}
2 分治算法 NBA循环赛日程安排
现在假设有8支队伍打比赛,那么假设第一天1和2打,3和4打,5和6打,7和8打。那么就有如下图的安排表。一共要打七天会打完。现在要把这个图分开四个部分来表示。
public static void main(String[] args) {
DisPatchPractice dispatch = new DisPatchPractice();
int table[][] = new int[8][8];
dispatch.getNBAGamePlan(table, 8);
for (int i = 0; i < table.length; i++) {
System.out.println();
for(int j=0;j<table.length;j++){
System.out.print(" "+table[i][j]);
}
}
}
3 分治算法 特殊点用L形数字包围
我实在不知道这个算法该怎么去描述,总之就是把一个特殊点用L给包围起来
private void getNBAGamePlan(int[][] table, int n) {
if (n == 1) {
table[0][0] = 1;
} else {
int m = n / 2;
// 填充左上部分
getNBAGamePlan(table, m);
// 填充右上部分
for (int i = 0; i < m; i++) { // 0,1,2,3
for (int j = m; j < n; j++) { // 4,5,6,7
table[i][j] = table[i][j - m] + m;
}
}
// 填充左下部分
for (int i = m; i < n; i++) {// 4,5,6,7
for (int j = 0; j < m; j++) { // 0,1,2,3
table[i][j] = table[i-m][j] + m;
}
}
// 填充右下部分
for (int i = m; i < n; i++) { // 4,5,6,7
for (int j = m; j < n; j++) { // 4,5,6,7
table[i][j] = table[i - m][j - m];
}
}
}
}
// 棋盘
private int[][] board;
// 特殊点的值
int specialDot = 0;
public ChessBoard(int specialRow, int specialCol, int size) {
super();
this.board = new int[size][size];
createChessBoard(specialRow, specialCol, 0, 0, size);
print();
}
//打印结果
private void print() {
for (int i = 0; i < board.length; i++) {
System.out.println();
for (int j = 0; j < board.length; j++) {
System.out.print(board[i][j]+" ");
}
}
}
public static void main(String[] args) {
int speciaRow = 5;
int specialCol = 5;
int size = 8;
ChessBoard chessBoard = new ChessBoard(speciaRow, specialCol, size);
}
/**
*
* @param specialRow
* 特殊点的横坐标
* @param specialCol
* 特殊点的纵坐标
* @param startRow
* 棋盘起点的横坐标
* @param startCol
* 棋盘起点的纵坐标
* @param size
*/
private void createChessBoard(int specialRow, int specialCol, int startRow,int startCol, int size) {
if (size == 1) {
return;
}
int half = size / 2;
specialDot = specialDot % 4 + 1;
// 如果特殊点在左上方
if (specialRow < startRow+half && specialCol < startCol+half) {
createChessBoard(specialRow, specialCol, startRow, startCol, half);
} else {
// 如果不在左上方 那么左上方的右下角的是特殊点
board[startRow + half - 1][startCol + half - 1] = specialDot;
createChessBoard(startRow + half-1, startCol + half-1, startRow,startCol, half);
}
// 如果特殊点在右上方
if (specialRow < startRow+half && specialCol >= startCol+half) {
createChessBoard(specialRow, specialCol,startRow,half + startCol, half);
} else {
// 如果不在右上方,那么右上方的左下角是特殊点
board[startRow + half - 1][startCol + half] = specialDot;
createChessBoard(startRow+half-1, startCol+half, startRow, startCol + half, half);
}
// 如果特殊点在左下方
if (specialRow >= startRow+half && specialCol < startCol+half) {
createChessBoard(specialRow , specialCol, startRow+half ,startCol, half);
} else {
// 如果不在左下方,那么左下方的右上角是特殊点
board[startRow + half][startCol + half - 1] = specialDot;
createChessBoard(startRow + half, startCol + half - 1, startRow+ half, startCol, half);
}
// 如果特殊点在右下方
if (specialRow >= startRow+half && specialCol >= startCol+half) {
createChessBoard(specialRow, specialCol, startRow+ half, startCol + half, half);
} else {
board[startRow + half][startCol + half] = specialDot;
createChessBoard(startRow + half, startCol + half, startRow + half,startCol + half, half);
}
}