题目描述
羊、狼、农夫都在岸边,当羊的数量小于狼的数量时,狼会攻击羊,农夫则会损失羊。农夫有一艘容量固定的船,能够承载固定数量的动物。
要求求出不损失羊情况下将全部羊和狼运到对岸需要的最小次数。只计算农夫去对岸的次数,回程时农夫不会运送羊和狼。
备注:农夫在或农夫离开后羊的数量大于狼的数量时狼不会攻击羊。
农夫自身不占用船的容量。
输入描述
第一行输入为M,N,X, 分别代表羊的数量,狼的数量,小船的容量。
输出描述
输出不损失羊情况下将全部羊和狼运到对岸需要的最小次数。
(若无法满足条件则输出0)
用例
示例1:
输入:
5 3 3
输出:
3
说明: 第一次运2只狼 第二次运3只羊 第三次运2只羊和1只狼
示例2:
输入:
5 4 1
输出:
0
说明:
如果找不到不损失羊的运送方案,输出0
个人解法
不保证通过率
public class Main {
public static int minTimes;//记录最小次数
/**
* 如需打印每种过河成功的过程 将isShow设为true
*/
public static boolean isShow = false;//是否打印过程
public static void main(String[] args) throws IOException {
// 处理输入
String[] input = new BufferedReader(new InputStreamReader(System.in)).readLine().split(" ");
int M = Integer.parseInt(input[0]), N = Integer.parseInt(input[1]), X = Integer.parseInt(input[2]);
minTimes = (M + N) * X;
// 表示已运输到对岸的羊、狼个数
int m_temp = 0;
int n_temp = 0;
//加了个HashMap用来记录下过河成功所经历的每次过程中运了多少只羊与狼
transport(M, N, X, m_temp, n_temp, 0, new HashMap<>());
if (minTimes == (M + N) * X) {
System.out.println(0);//从未成功过
} else {
System.out.println(minTimes);
}
}
// m0, n0 分别表示剩余的羊、狼个数, x为船容量
// m1, n1 分别表示运输到对岸的羊、狼个数,times为次数
public static void transport(int m0, int n0, int x, int m1, int n1, int times, HashMap<Integer, int[]> map) {
//若可以一次性运走,结束了,注意等于号。。。
if (x >= m0 + n0) {
if (times + 1 < minTimes) {
minTimes = times + 1;
}
map.put(times + 1, new int[]{m0, n0});
if (isShow) {
for (int i = 1; i <= times + 1; i++) {
System.out.print(Arrays.toString(map.get(i)));
}
System.out.print("\ttimes:" + (times + 1) + "\n");
}
return;
}
//尝试运一部分狼一部分羊
//要上船的羊数量不可以超过岸上数量、也不可以超过船的容量
for (int i = 0; i <= Math.min(m0, x); i++) {
//要上船的狼的数量不可以超过岸上数量、也不可以超过船装了羊后的剩余的容量
for (int j = 0; j <= Math.min(x - i, n0); j++) {
//不可以不运
if (i + j == 0) {
continue;
}
//船离岸后,原来这岸,要么没有羊,要么羊比狼多,才可以运;对岸也要检查,不考虑回程带动物
if ((m0 - i == 0 || m0 - i > n0 - j) && (m1 + i == 0 || m1 + i > n1 + j)) {
//运一次
map.put(times + 1, new int[]{i, j});
transport(m0 - i, n0 - j, x, m1 + i, n1 + j, times + 1, map);
}
}
}
}
}