好久没写算法的问题了,感觉退步了很多。写了一道过河的问题,想了一下午用深度遍历憋出来了,结果复杂度有点多,以后再试试别的解法吧。
题目大意:
野人和传教士过河,野人传教士的数目相同,船的负载为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--) {//man
for (int j = boat-i; j >= 0; j--) {//eat man
if (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++) {//man
for (int j = 0; j <= boat-i; j++) {//eat man
if (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;
}
}