过河问题的递归解法

来源:互联网 发布:西安软件行业优惠 编辑:程序博客网 时间:2024/04/28 14:50

好久没写算法的问题了,感觉退步了很多。写了一道过河的问题,想了一下午用深度遍历憋出来了,结果复杂度有点多,以后再试试别的解法吧。

题目大意:

野人和传教士过河,野人传教士的数目相同,船的负载为M(1<M<=5),野人传教士全会划船,若野人数量大于传教士则会吃掉传教士,求划船的最小次数。

输入格式 :

第一行:为测试的个数

第二行:野人和传教士的数目N, 船的负载M

例如:

3
3 2
4 3
5 2

思想:

设A->B岸运输,即A为出发地点,B为终点

1  A点,B点船上的人数要求都是 传教士大于野人,除非没有传教士

2 若将出发地做标记,则出发地为人数为0,成功,或者若出发地人数小于船的负载且靠A岸则直接可以+1后成功。

3 A->B时 船上的人数要大于1, B->A无限制

4 以A岸人数为代表,若人数重复则此次无效。注意此题船在A岸和B岸要分开考虑,人数相同但船在A岸和B岸是不同情况 

import java.util.Scanner;public class Algorithm {static int Answer;static int buffer[][] = new int[25][4];static int manCount;//记录人数public static void main(String args[]) throws Exception{Scanner sc = new Scanner(System.in);int T = sc.nextInt();for(int test_case = 0; test_case < T; test_case++) {int man = sc.nextInt();// 传教士和野人的人数int boat = sc.nextInt();//船的负载manCount = man;int count = 0;//船行驶即时的数目,用于递归传值Answer = 9999; //取最优值,故初始化一个大的值function(man, man , 0, 0, boat, count);System.out.println("Case #"+(test_case+1));if (Answer != 9999) {System.out.println(Answer);} else {System.out.println("impossible");}}}private static void function(int man, int eman, int bankman, int bankeman, int boat, int count) {if (count > 17) {return ;}if ((man < eman && man!=0 && eman!=0) || (bankman < bankeman && bankman!=0 && bankeman!=0)) {//野人大于传教士的情况return ;}count++;int k;if (count%2 == 1) { //count为单数时,为A->B的情况if (man+eman <= boat) {//若A岸上的人数小于船的负载,则可直接记录为一个解if (Answer > count)//成功但不一定是最优解Answer = count;//递归完成后取最小值为最优解return;}for ( k = 0; k < 25; k++) {//此时为检查有没有重复以前的情况if (buffer[k][0] == 0 && buffer[k][1] == 0) {break;}if (buffer[k][0] == man && buffer[k][1] == eman) {return ;}}buffer[k][0] = man;buffer[k][1] = eman;for (int i = boat; i >= 0; i--) {//manfor (int j = boat-i; j >= 0; j--) {//eat manif (i+j > 1 && i+j <= boat && (i >= j || i==0 || j==0)&& !(i==0&&j==0)&& man-i >= 0 && eman-j >= 0) {//i为传教士j为野人int newman = man - i;int neweman = eman - j;int bnewman = manCount-newman;int bneweman = manCount-neweman;if (newman>=0 && neweman>=0 && bnewman>=0 && bneweman>=0) {function(newman,neweman,bnewman,bneweman,boat,count);}}}}buffer[k][0] = 0;buffer[k][1] = 0;} else {//B->A的情况for ( k = 0; k < 25; k++) {if (buffer[k][2] == 0 && buffer[k][3] == 0) {break;}if (buffer[k][2] == man && buffer[k][3] == eman) {return;}}buffer[k][2] = man;buffer[k][3] = eman;//回A岸for (int i = 0; i <= boat; i++) {//manfor (int j = 0; j <= boat-i; j++) {//eat manif (i+j <= boat && (i >= j || i==0 || j==0)&& !(i==0&&j==0)&& bankman-i >= 0 && bankeman-j >= 0) {int newman = bankman - i;int neweman = bankeman - j;int bnewman = manCount-newman;int bneweman = manCount-neweman;if (newman>=0 && neweman>=0 && bnewman>=0 && bneweman>=0) {function(bnewman,bneweman,newman,neweman,boat,count);}}}}buffer[k][2] = 0;buffer[k][3] = 0;}return;}}

0 0