1.百钱买百鸡
/*** 百钱买百鸡* 鸡翁一,值钱五,鸡母一,值钱三,鸡雏三值钱一,百钱买百鸡,问翁,母、雏各几何?* 释义:* 公鸡5文钱一只,母鸡3文钱一只,小鸡3只一文钱。如果用100文钱买100只鸡,那么,公鸡、母鸡、小鸡各应该买多少只?*/public static void buyChooks() {int money = 100;//钱数int chooks = 100;//鸡的总数boolean hasSolution = false;for (int cocks = 0; cocks <= chooks; cocks++) {//公鸡的数量for (int hens = 0; hens <= chooks; hens++) {//母鸡的数量int chickens = chooks - cocks - hens;//小鸡的数量if (cocks * 5 + hens * 3 + chickens / 3.0 == money) {hasSolution = true;//%2d=结果以2位整数输出,如果不足,前面用空格补位System.out.printf("公鸡[ %2d ]只,母鸡[ %2d ]只,小鸡[ %2d ]只 \n", cocks, hens, chickens);}}}if (!hasSolution) {System.out.printf("求解完成。无解!");}}
调用:
buyChooks();
输出:
公鸡[ 0 ]只,母鸡[ 25 ]只,小鸡[ 75 ]只公鸡[ 4 ]只,母鸡[ 18 ]只,小鸡[ 78 ]只公鸡[ 8 ]只,母鸡[ 11 ]只,小鸡[ 81 ]只公鸡[ 12 ]只,母鸡[ 4 ]只,小鸡[ 84 ]只
2.五家共井
/*** 五家共井* 今有五家共井,甲二绠不足如乙一绠,乙三绠不足如丙一绠,丙四绠不足如丁一绠,丁五绠不足如戊一绠,戊六绠不足如甲一绠。* 如各得所不足一绠,皆逮。问井深,绠长各几何?* 释义:* 绠:绳索,逮:到达井底。* 现在有五家共用一口井,甲乙丙丁戍各有一条绳子汲水,* 甲绳*2 + 乙绳 = 井深,* 乙绳*3 + 丙绳 = 井深,* 丙绳*4 + 丁绳 = 井深,* 丁绳*5 + 戊绳 = 井深,* 戊绳*6 + 甲绳 = 井深,* 求甲乙丙丁戊的绳子长度和井深。* 解:* 假设所有绳子长度和井的深度都是正整数* 甲绳=乙绳+丙绳/2;* 乙绳=丙绳+丁绳/3;* 丁绳=戊绳+甲绳/5;* 因为都是整数,所以:* 丙绳必为2的整倍数;* 丁绳必为3的整倍数;* 戊绳必为4的整倍数;* 甲绳必为5的整倍数;*/public static void oneWellFiveUsers() {int len1, len2, len3, len4, len5, len;//定义甲乙丙丁戊的绳子长度和井深for (len5 = 4; ; len5 += 4) {//戊绳for (len1 = 5; ; len1 += 5) {//甲绳len4 = len5 + len1 / 5;//丁绳if (len4 % 3 != 0) {//丁绳不是3的整倍数continue;}len3 = len4 + len5 / 4;//丙绳if (len3 % 2 != 0) {//丙绳不是2的整倍数continue;}len2 = len3 + len4 / 3;//乙绳if (len2 + len3 / 2 < len1) {//切回len5循环,因为len1太长了。break;}if (len2 + len3 / 2 == len1) {len = 2 * len1 + len2;System.out.printf("各自绳长为:甲[%d],乙[%d],丙[%d],丁[%d],戊[%d];井深[%d]", len1, len2, len2, len4, len5, len);return;}}}}
调用:
oneWellFiveUsers();
输出:
各自绳长为:甲[265],乙[191],丙[191],丁[129],戊[76];井深[721]
3.鸡兔同笼
参考 常用算法指南(一)基本算法思想 ,3.1 穷举算法思想
4.猴子吃桃
/*** 猴子吃桃* 某天一只猴子摘了一堆桃子,具体多少不知道,猴子每天吃了其中一半然后在多吃一个,* 第二天则吃剩余的一半然后再多吃一个,长此往复,直到第10天,猴子发现只有一个桃子了。问这只猴子在第一天摘了多少个桃子?* 解:* 由题可知* a₁₀ = 1;* a₉ = (a₁₀ + 1) * 2;* 。。。* a₂ = (a₃ + 1) * 2;* a₁ = (a₂ + 1) * 2* 所以,第一天的桃子是第二天的桃子数量+1的2倍*/public static int monkeyEatPeaches(int day) {int peach = 1;if (day == 10) {//第十天的桃子return peach;}peach = (monkeyEatPeaches(day + 1) + 1) * 2;//第一天的桃子是第二天的桃子数量+1的2倍return peach;}
调用:
int day = 1;int peaches = monkeyEatPeaches(day);System.out.println("猴子第一天的桃子数量为:" + peaches);
输出:
猴子第一天的桃子数量为:1534
5.舍罕王赏麦
/*** 舍罕王赏麦* 传说国际象棋的发明者是古印度的西萨·班·达一尔,当时的国王是舍罕,世人称为舍罕王。* 当时舍罕王比较贪玩,畏惧在想的西萨·班·达一尔发明了国际象棋献给舍罕王。* 舍罕王非常喜欢,为了奖励西萨·班·达一尔,便许诺可以满足他踢出的任何要求。* 西萨·班·达一尔灵机一动,指着8*9=64的棋盘说:“陛下,请您按照棋盘的格子上次我一点麦子吧,* 第一个小格赏我1粒麦子,第二个小格赏我2粒,第三个小格赏4粒,以后每一小格都比钱一个小格赏的麦粒数增加一倍,* 只要把棋盘上全部的64个小格按照这样方法得到的麦粒都赏赐给我,我就心满意足了。”* 舍罕王觉得这是一个很小的要求,就满口答应了,命人按照要求准备麦子。* 但是,不就大臣计算的结果令舍罕王大惊失色。问题是:舍罕王需要赏赐出多少粒麦子?* 解:* 第一格:2⁰ = 1;* 第二格:2¹ = 2;* 第三格:2² = 4;* 第四格:2³ = 8;* ……* 第六十四格:2⁶³=* 将每一格的数量加起来:* sum = 2⁰+2¹+2²+……+2⁶³;* 用求和公式表示为:* ₆₃* ∑ 2ⁱ* ⁱ⁼⁰** @param gridNum 格子数量*/public static void rewardWheat(int gridNum) {double temp = 1;//每一格的数量double sum = 0;//总数for (int i = 0; i < gridNum; i++) {if (i == 0) {//第一格是1粒temp = 1;} else {temp *= 2;//从第二格开始,都是2的i-1次幂}sum += temp;}System.out.println("舍罕王需要赏赐出麦子粒数为: " + sum);}static long count = 0;
调用:
int gridNum = 64;rewardWheat(gridNum);
输出:
舍罕王需要赏赐出麦子粒数为: 1.8446744073709552E19
这个结果相当于:1.8446744073709552乘10的19次方,19位数,而1亿是9尾数,而一兆(万亿为兆),也才是10的12次方.
6.汉诺塔

/*** 汉诺塔* 又称为河内塔。勃拉玛是古印度的一个开天辟地的神,其在一个庙宇中留下了三根金刚石棒。* 第一根上面套着64个大小不一的圆形金片。其中,最大的金片在最底下,其余的依次叠上去,且一个比一个小。* 勃拉玛要求众僧将该金刚石棒中的金片逐一移到另一根棒上,* 规定依次只能移动一个金片,且金片在放到棒上时,大的只能放在小的下面,但是可以利用中间的一根棒作为辅助移动使用。** @param n 圆盘数* @param a 第一根金刚石棒* @param b 中间的辅助石棒* @param c 第三根金刚石棒*/public static void hanoiGame(int n, char a, char b, char c) {if (n == 1) {//圆盘数为1,直接从a移动到cSystem.out.printf("第 %2d 次移动:圆盘从%c棒移动到%c棒\n", ++count, a, c);} else {//剩余圆盘数不为1,借助中间辅助的石棒进行移动hanoiGame(n - 1, a, c, b);System.out.printf("第 %2d 次移动:圆盘从%c棒移动到%c棒\n", ++count, a, c);hanoiGame(n - 1, b, a, c);}}
调用:
hanoiGame(4, 'A', 'B', 'C');//圆盘数量越多,需要消耗的步数将成几何级增长。所以此处以4位例。
输出:
第 1 次移动:圆盘从A棒移动到B棒第 2 次移动:圆盘从A棒移动到C棒第 3 次移动:圆盘从B棒移动到C棒第 4 次移动:圆盘从A棒移动到B棒第 5 次移动:圆盘从C棒移动到A棒第 6 次移动:圆盘从C棒移动到B棒第 7 次移动:圆盘从A棒移动到B棒第 8 次移动:圆盘从A棒移动到C棒第 9 次移动:圆盘从B棒移动到C棒第 10 次移动:圆盘从B棒移动到A棒第 11 次移动:圆盘从C棒移动到A棒第 12 次移动:圆盘从B棒移动到C棒第 13 次移动:圆盘从A棒移动到B棒第 14 次移动:圆盘从A棒移动到C棒第 15 次移动:圆盘从B棒移动到C棒
7.窃贼问题
/*** 窃贼问题* 有一个窃贼带着一个背包去偷东西,房屋共有5件物品,其重量和价值如下:* 物品1: 6公斤,48元;* 物品2:5公斤,40元;* 物品3:2公斤,12元;* 物品4: 1公斤,8元;* 物品5:1公斤,7元;* 窃贼希望能够拿到最大价值的东西,而窃贼的背包最多可以装重量8公斤的物品,那么窃贼应该装那些物品才能达到要求。* 解:* 这个题可以采用数学的排列组合思想* 将所有不超过8公斤的组合进行对比,找出总价值最大的那个组合即可* 将所有物品按照价值排序,先拿出价值最大的,再从剩余的的物品中拿出价值最大的,看看总重量有没有超重,没有超重就放入,* 超重就换下一个价值较大的,以此类推。便可以得到一个组合,然后再拿第二个和其他物品进行组合,对比之前哪个总价值比较大** @param articles 所有物品*/public static void thief(List<Article> articles) {int QUOTA_WEIGHT = 8;int maxValue = 0;List<Article> maxArticles = new ArrayList<>();Collections.sort(articles, new Comparator<Article>() {@Overridepublic int compare(Article o1, Article o2) {if (o1.value > o2.value) {return -1;} else if (o1.value < o2.value) {return 1;} else {return 0;}}});//开始获取组合,先拿出价值最大的,再从剩余的的物品中拿出价值最大的,看看总重量有没有超重,没有超重就放入,超重就换下一个for (int i = 0; i < articles.size(); i++) {Article article = articles.get(i);int articleValue = article.value;int articleWeight = article.weight;int tempValue = articleValue;int tempWeight = articleWeight;List<Article> tempArticles = new ArrayList<>();tempArticles.add(article);for (int j = 0; j < articles.size(); j++) {Article article2 = articles.get(j);if (article2 == article) {continue;}int article2Value = article2.value;int article2Weight = article2.weight;if (tempWeight + article2Weight <= QUOTA_WEIGHT) {tempWeight += article2Weight;tempValue += article2Value;tempArticles.add(article2);}if (tempValue > maxValue) {//当前价值已经超过之前记录的最大值maxValue = tempValue;maxArticles.clear();tempArticles.forEach(maxArticles::add);}if (tempWeight >= QUOTA_WEIGHT) {//当前重量已达到最大值break;}}}System.out.printf("不超过[%d]公斤的物品的最大价值为: %d\n", QUOTA_WEIGHT, maxValue);System.out.print("物品为:");maxArticles.forEach(e -> {System.out.print(e.name + ",");});System.out.print("\n");}//物品static class Article {String name;//物品名称int value;//物品价值int weight;//物品重量public Article(String name, int value, int weight) {this.name = name;this.value = value;this.weight = weight;}}
调用:
List<Article> articles = new ArrayList<>();articles.add(new Article("商品1", 48, 6));articles.add(new Article("商品2", 40, 5));articles.add(new Article("商品3", 12, 2));articles.add(new Article("商品4", 8, 1));articles.add(new Article("商品5", 7, 1));thief(articles);
输出:
不超过[8]公斤的物品的最大价值为: 63物品为:商品4,商品1,商品5,
8.马踏棋盘
/*** 马踏棋盘* 国际象棋的棋盘有8行8列6个单元格,无论将马放于棋盘的哪个单元格,都可以让马踏遍棋盘的每个单元格。* 问马该怎么走才可以踏遍棋盘的每个单元格*/public static void horseTreadChessboard(Coordinate coordinate) {Coordinate next = new Coordinate(0, 0);if (coordinate.x < 0 || coordinate.x > 7 || coordinate.y < 0 || coordinate.y > 7) {//已出棋盘return;}if (chessboard[coordinate.x][coordinate.y] != 0) {//已经走过这里return;}chessboard[coordinate.x][coordinate.y] = stepNum;//记录当前坐标是第几步走的stepNum++;if (stepNum > 64) {//全部走完,输出for (int x = 0; x < 8; x++) {for (int y = 0; y < 8; y++) {System.out.printf("[%d][%d] 第 %2d 步 \n", x, y, chessboard[x][y]);}}} else {for (int i = 0; i < 8; i++) {next.x = coordinate.x + COORDINATE[i].x;next.y = coordinate.y + COORDINATE[i].y;if (next.x < 0 || next.x > 7 || next.y < 0 || next.y > 7) {//当前方向越界continue;}horseTreadChessboard(next);}}// chessboard[coordinate.x][coordinate.y] = 0;//清除步数序号// stepNum--;//减少步数}static int[][] chessboard = new int[8][8];//马所走过的棋盘的横纵坐标static int stepNum = 1;//总共走过的步数//马可以移动的八个方向坐标static final Coordinate[] COORDINATE = {new Coordinate(-1, -2),//横向左移1位,纵向上移2位new Coordinate(-1, 2),new Coordinate(1, -2),new Coordinate(1, 2),//横向右移1位,纵向下移2位new Coordinate(-2, -1),new Coordinate(-2, 1),new Coordinate(2, -1),new Coordinate(2, 1),};//马可以移动的方向static class Coordinate {int x;//横向坐标int y;//纵向坐标public Coordinate(int x, int y) {this.x = x;this.y = y;}}
调用:
Coordinate startLocation = new Coordinate(1, 1);//初始位置horseTreadChessboard(startLocation);
输出:
[0][0] 第 27 步[0][1] 第 24 步[0][2] 第 7 步[0][3] 第 2 步[0][4] 第 35 步[0][5] 第 43 步[0][6] 第 21 步[0][7] 第 4 步[1][0] 第 8 步[1][1] 第 1 步[1][2] 第 26 步[1][3] 第 23 步[1][4] 第 6 步[1][5] 第 3 步[1][6] 第 34 步[1][7] 第 42 步[2][0] 第 25 步[2][1] 第 28 步[2][2] 第 9 步[2][3] 第 18 步[2][4] 第 36 步[2][5] 第 22 步[2][6] 第 5 步[2][7] 第 20 步[3][0] 第 10 步[3][1] 第 17 步[3][2] 第 37 步[3][3] 第 29 步[3][4] 第 12 步[3][5] 第 19 步[3][6] 第 41 步[3][7] 第 33 步[4][0] 第 38 步[4][1] 第 30 步[4][2] 第 11 步[4][3] 第 45 步[4][4] 第 40 步[4][5] 第 32 步[4][6] 第 13 步[4][7] 第 62 步[5][0] 第 16 步[5][1] 第 46 步[5][2] 第 39 步[5][3] 第 31 步[5][4] 第 14 步[5][5] 第 44 步[5][6] 第 51 步[5][7] 第 56 步[6][0] 第 54 步[6][1] 第 59 步[6][2] 第 15 步[6][3] 第 47 步[6][4] 第 52 步[6][5] 第 57 步[6][6] 第 63 步[6][7] 第 50 步[7][0] 第 61 步[7][1] 第 48 步[7][2] 第 53 步[7][3] 第 58 步[7][4] 第 64 步[7][5] 第 49 步[7][6] 第 55 步[7][7] 第 60 步
9.八皇后问题
/*** 八皇后问题* 八皇后问题是高斯于1850年提出,是一个典型的回溯算法的问题。大意如下:* 国际象棋的棋盘有8行8列共64个单元格,在棋盘上摆放八个皇后,使其不能互相攻击,* 也就是说任意两个皇后都不能处于同一行、同一列或同一斜线上。问总共有多少种摆放方法,每一种摆放方式是怎样的。* 目前数学上可以证明八皇后问题总共有92种解。* <p>* 解:* 由题目可知,每一行只能放一个,每一列也只能放一个,* 所以,我们可以估计放置的时候,一行一行的放,只要下一行的放置不和之前放置的处于同一列,并且不处于同一斜线上就可以了。** @param row 第几行的棋子,也就是第几个棋子*/public static void eightQueen(int row) {if (row == ROWS) {//放置完毕,输出System.out.println("*********解法" + solutionNum++ + "*********");eightQueenOutput();return;}boolean canPut;for (int i = 1; i <= 8; i++) {columns[row] = i;canPut = true;for (int j = 0; j < row; j++) {if (columns[j] == columns[row]) {canPut = false;} else if (Math.abs(columns[j] - columns[row]) == (row - j)) {canPut = false;}}if (canPut) {eightQueen(row + 1);} else {//这行无法放置,直接舍弃之前的摆法。}}}public static void eightQueenOutput() {for (int r = 0; r < ROWS; r++) {int column = columns[r];for (int c = 1; c < column; c++) {if ((r + c) % 2 == 0) {System.out.print("■ ");//棋盘空位} else {System.out.print("□ ");//棋盘空位}}System.out.print("☆ ");//皇后放置的位置for (int c = column; c < 8; c++) {if ((r + c) % 2 == 0) {System.out.print("■ ");} else {System.out.print("□ ");}}System.out.print("\n");}}static int solutionNum = 1;//解法计数器static int ROWS = 8;//棋子放置的总行数。从第0行开始static int[] columns = new int[8];//每一个棋子处于每一行的第几列。第一个元素就是处于第一行,第二个就是处于第二行。
调用:
int r = 0;eightQueen(r);
输出:
*********解法1*********☆ □ ■ □ ■ □ ■ □■ □ ■ □ ☆ ■ □ ■□ ■ □ ■ □ ■ □ ☆■ □ ■ □ ■ ☆ □ ■□ ■ ☆ □ ■ □ ■ □■ □ ■ □ ■ □ ☆ ■□ ☆ ■ □ ■ □ ■ □■ □ ■ ☆ □ ■ □ ■*********解法2*********☆ □ ■ □ ■ □ ■ □■ □ ■ □ ■ ☆ □ ■□ ■ □ ■ □ ■ □ ☆■ □ ☆ ■ □ ■ □ ■□ ■ □ ■ □ ■ ☆ □■ □ ■ ☆ □ ■ □ ■□ ☆ ■ □ ■ □ ■ □■ □ ■ □ ☆ ■ □ ■*********解法n*********由于输出太多,此处省略部分解法的输出,可以自行运行代码输出。*********解法91*********□ ■ □ ■ □ ■ □ ☆■ □ ☆ ■ □ ■ □ ■☆ □ ■ □ ■ □ ■ □■ □ ■ □ ■ ☆ □ ■□ ☆ ■ □ ■ □ ■ □■ □ ■ □ ☆ ■ □ ■□ ■ □ ■ □ ■ ☆ □■ □ ■ ☆ □ ■ □ ■*********解法92*********□ ■ □ ■ □ ■ □ ☆■ □ ■ ☆ □ ■ □ ■☆ □ ■ □ ■ □ ■ □■ □ ☆ ■ □ ■ □ ■□ ■ □ ■ □ ☆ ■ □■ ☆ □ ■ □ ■ □ ■□ ■ □ ■ □ ■ ☆ □■ □ ■ □ ☆ ■ □ ■
10.寻找真假银币
/*** 寻找假银币* 现有8枚银币,其中一枚是假币。但是,从外观和做工上无法分辨哪枚是真币哪枚是假币,只知道假币的重量要比真币轻。* 要求仅使用一个天平,如何以最少的步骤寻找的假币。* 解法,2分法查找(分治思想)* 将硬币按照数量分为两等分,放在天平两边,较轻的一边肯定有假币,* 再将较轻的那组分为2等分,重复上面的步骤,直到天平两边都只剩下一个硬币,那个较轻的就是假币** @param coins 包含一个假币的银币数组。* @param min 包含假币的数组中的起始坐标 index* @param max 包含假币的数组的结束坐标 index*/public static int findFakeSilverCoin(int[] coins, int min, int max) {int size = max - min + 1;//银币的总数量int weightLeft = 0, weightRight = 0;int mid;//中间值if (size % 2 == 0) {//银币数量为偶数//直接分为两等分,重量小的那一组包含假币mid = (max + min + 1) / 2;//中间值for (int i = min; i < mid; i++) {weightLeft += coins[i];}for (int i = mid; i <= max; i++) {weightRight += coins[i];}if (weightLeft < weightRight) {if (size == 2) {return min;}return findFakeSilverCoin(coins, min, mid);} else {if (size == 2) {return max;}return findFakeSilverCoin(coins, mid, max);}} else {//银币数量为奇数//拿出一个硬币,将剩余的硬币分为两等分,如果这两份的重量一致,则拿出的那个就是假币,如果不一致,重量轻的那一组有假币int temp = max;max = max - 1;mid = (max + min + 1) / 2;//中间值for (int i = min; i < mid; i++) {weightLeft += coins[i];}for (int i = mid; i <= max; i++) {weightRight += coins[i];}if (weightLeft < weightRight) {if (size == 3) {return min;}return findFakeSilverCoin(coins, min, mid);} else if (weightLeft > weightRight) {if (size == 3) {return max;}return findFakeSilverCoin(coins, mid, max);} else {return temp;}}}
调用:
int[] coins = new int[8];Arrays.parallelSetAll(coins, index -> 2);//初始化各个银币的重量为2coins[4] = 1;//假银币的重量为1int fakeIndex = findFakeSilverCoin(coins, 0, coins.length - 1);System.out.println("假银币的编号为:" + (fakeIndex + 1));//编号为index+1,因为index是从0开始,编号从1开始
输出:
假银币的编号为:5
11.青蛙过河

/*** 青蛙过河* 一条河之间有若干个石块间隔,有两队青蛙同时从两边开始过河,每队3只青蛙,这些青蛙只能向前移动,不能向后移动,且一次只能有一只青蛙移动。* 在移动过程中,青蛙可以向前面的空位中移动,不可以一次跳过两个位置,但是可以跳过对方一只青蛙进入前面的一个空位。* 问两队青蛙该如何移动才能够用最少的步数分别走向对岸*/public static void frogCrossRiver(List<Frog> frogList) {for (Frog frog : frogList) {if (!frog.canJump) {continue;}int index = frogList.indexOf(frog);int frontIndex = index + frog.jumpDirection;int emptyPosition = frog.frogPosition + frog.jumpDirection;Frog empty;if (frontIndex > 0 && frontIndex < frogList.size()) {empty = frogList.get(frontIndex);if (empty.team != 0) {emptyPosition = frog.frogPosition + 2 * frog.jumpDirection;}}System.out.printf("青蛙 [%s] 从位置 %d 向 %s 跳到位置 %d。\n", frog.frogName,frog.frogPosition, frog.jumpDirection == 1 ? "右" : "左", emptyPosition);frogStepNum++;updateFrogQueue(frogList, frog);if (finish) {if (checkFrogCrossSuccess(frogList)) {System.out.println("过河成功!总共步数为:" + frogStepNum);} else {System.out.println("过河失败!消耗步数为:" + frogStepNum);}return;}frogCrossRiver(frogList);}}static boolean finish = false;static int frogStepNum = 0;private static Frog updateFrogQueue(List<Frog> frogList, Frog frog) {//将两个frog交换位置,被交换的那个只能是空位int index = frogList.indexOf(frog);int jumpDirection = frog.jumpDirection;//青蛙跳的方向int jumpDistance = jumpDirection;//青蛙跳的距离int emptyIndex = index + jumpDistance;//青蛙跳向的那个位置的indexFrog empty;//青蛙跳向的那个位置if (emptyIndex < 0 || emptyIndex >= frogList.size()) {//青蛙跳向的地方已经过河了empty = new Frog(0, "___", frog.frogPosition + jumpDistance, 0, false);} else {empty = frogList.get(emptyIndex);}if (empty.team != 0) {//青蛙可以向前跳一步到空位,或者跳过对方一只青蛙进入前面的一个空位。jumpDistance = 2 * jumpDirection;emptyIndex = index + jumpDistance;if (emptyIndex < 0 || emptyIndex >= frogList.size()) {empty = new Frog(0, "___", frog.frogPosition + jumpDistance, 0, false);} else {empty = frogList.get(emptyIndex);}if (empty.team != 0) {throw new RuntimeException("ERROR : 青蛙" + frog.frogName + "要跳向的地方" + empty.frogPosition + "不是空位!");}}frog.frogPosition = frog.frogPosition + jumpDistance;empty.frogPosition = frog.frogPosition - jumpDistance;if (emptyIndex < 0 || emptyIndex > 6) {frogList.set(index, empty);//青蛙跳向的地方已经过河了,直接在青蛙所在位置换一个空位} else {frogList.set(emptyIndex, frog);frogList.set(index, empty);}System.out.println("现在过河情况为:");for (Frog f : frogList) {System.out.print(f.frogName + " ");}System.out.print("\n");finish = true;//重新判断青蛙是不是可以向前跳for (int i = 0; i < frogList.size(); i++) {Frog f = frogList.get(i);if (f.team == 0) {continue;}f.canJump = false;int frontIndex = i + f.jumpDirection;if (frontIndex < 0 || frontIndex >= frogList.size()) {f.canJump = true;finish = false;continue;}Frog frontFrog = frogList.get(frontIndex);if (frogStepNum % 3 != 2 && frontFrog.team == 0 && f.team != frog.team) {f.canJump = true;finish = false;}if (frogStepNum % 3 == 2 && frontFrog.team == 0 && f.team == frog.team) {f.canJump = true;finish = false;}int frontIndex1 = i + 2 * f.jumpDirection;if (frontIndex1 < 0 || frontIndex1 >= frogList.size()) {f.canJump = true;finish = false;continue;}Frog frontFrog1 = frogList.get(frontIndex1);if (frontFrog1.team == 0 && f.team != frontFrog.team) {f.canJump = true;finish = false;}// if (empty.frogPosition - f.frogPosition > 0 && empty.frogPosition - f.frogPosition < 3// && f.jumpDirection == 1) {//空位左侧3个位置以内还有team1的青蛙// f.canJump = true;// finish = false;// }// if (f.frogPosition - empty.frogPosition > 0 && f.frogPosition - empty.frogPosition < 3// && f.jumpDirection == -1) {//空位右侧3个位置以内还有team2的青蛙// f.canJump = true;// finish = false;// }}return empty;}static boolean checkFrogCrossSuccess(List<Frog> frogList) {boolean success = true;for (Frog frog : frogList) {if (frog.team != 0) {success = false;break;}}return success;}static List<Frog> initFortQueue() {List<Frog> frogList = new ArrayList<>();frogList.add(new Frog(1, "左①", 0, 1, false));frogList.add(new Frog(1, "左②", 1, 1, false));frogList.add(new Frog(1, "左③", 2, 1, true));frogList.add(new Frog(0, "___", 3, 0, false));frogList.add(new Frog(2, "右①", 4, -1, true));frogList.add(new Frog(2, "右②", 5, -1, false));frogList.add(new Frog(2, "右③", 6, -1, false));return frogList;}/*** 青蛙*/static class Frog {int team;//青蛙所属队伍String frogName;//青蛙名称int frogPosition;//青蛙当前位置int jumpDirection;//可以跳动的方向-1.向左,1向右boolean canJump;//是否可以跳动public Frog(int team, String frogName, int frogPosition, int jumpDirection, boolean canJump) {this.team = team;this.frogName = frogName;this.frogPosition = frogPosition;this.jumpDirection = jumpDirection;this.canJump = canJump;}}
调用:
List<Frog> frogList = initFortQueue();System.out.println("青蛙初始位置为:");for (Frog f : frogList) {System.out.print(f.frogName + " ");}System.out.print("\n");frogCrossRiver(frogList);
输出:
青蛙初始位置为:左① 左② 左③ ___ 右① 右② 右③青蛙 [左③] 从位置 2 向 右 跳到位置 3。现在过河情况为:左① 左② ___ 左③ 右① 右② 右③青蛙 [右①] 从位置 4 向 左 跳到位置 2。现在过河情况为:左① 左② 右① 左③ ___ 右② 右③青蛙 [右②] 从位置 5 向 左 跳到位置 4。现在过河情况为:左① 左② 右① 左③ 右② ___ 右③青蛙 [左③] 从位置 3 向 右 跳到位置 5。现在过河情况为:左① 左② 右① ___ 右② 左③ 右③青蛙 [左②] 从位置 1 向 右 跳到位置 3。现在过河情况为:左① ___ 右① 左② 右② 左③ 右③青蛙 [左①] 从位置 0 向 右 跳到位置 1。现在过河情况为:___ 左① 右① 左② 右② 左③ 右③青蛙 [右①] 从位置 2 向 左 跳到位置 0。现在过河情况为:右① 左① ___ 左② 右② 左③ 右③青蛙 [右①] 从位置 0 向 左 跳到位置 -1。现在过河情况为:___ 左① ___ 左② 右② 左③ 右③青蛙 [右②] 从位置 4 向 左 跳到位置 2。现在过河情况为:___ 左① 右② 左② ___ 左③ 右③青蛙 [右②] 从位置 2 向 左 跳到位置 0。现在过河情况为:右② 左① ___ 左② ___ 左③ 右③青蛙 [右②] 从位置 0 向 左 跳到位置 -1。现在过河情况为:___ 左① ___ 左② ___ 左③ 右③青蛙 [左③] 从位置 5 向 右 跳到位置 7。现在过河情况为:___ 左① ___ 左② ___ ___ 右③青蛙 [左②] 从位置 3 向 右 跳到位置 4。现在过河情况为:___ 左① ___ ___ 左② ___ 右③青蛙 [左①] 从位置 1 向 右 跳到位置 2。现在过河情况为:___ ___ 左① ___ 左② ___ 右③青蛙 [左①] 从位置 2 向 右 跳到位置 3。现在过河情况为:___ ___ ___ 左① 左② ___ 右③青蛙 [右③] 从位置 6 向 左 跳到位置 5。现在过河情况为:___ ___ ___ 左① 左② 右③ ___青蛙 [左②] 从位置 4 向 右 跳到位置 6。现在过河情况为:___ ___ ___ 左① ___ 右③ 左②青蛙 [左①] 从位置 3 向 右 跳到位置 4。现在过河情况为:___ ___ ___ ___ 左① 右③ 左②青蛙 [右③] 从位置 5 向 左 跳到位置 3。现在过河情况为:___ ___ ___ 右③ 左① ___ 左②青蛙 [右③] 从位置 3 向 左 跳到位置 2。现在过河情况为:___ ___ 右③ ___ 左① ___ 左②青蛙 [右③] 从位置 2 向 左 跳到位置 1。现在过河情况为:___ 右③ ___ ___ 左① ___ 左②青蛙 [右③] 从位置 1 向 左 跳到位置 0。现在过河情况为:右③ ___ ___ ___ 左① ___ 左②青蛙 [右③] 从位置 0 向 左 跳到位置 -1。现在过河情况为:___ ___ ___ ___ 左① ___ 左②青蛙 [左②] 从位置 6 向 右 跳到位置 7。现在过河情况为:___ ___ ___ ___ 左① ___ ___青蛙 [左①] 从位置 4 向 右 跳到位置 5。现在过河情况为:___ ___ ___ ___ ___ 左① ___青蛙 [左①] 从位置 5 向 右 跳到位置 6。现在过河情况为:___ ___ ___ ___ ___ ___ 左①青蛙 [左①] 从位置 6 向 右 跳到位置 7。现在过河情况为:___ ___ ___ ___ ___ ___ ___过河成功!总共步数为:27
