版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Gods_magic/article/details/53706990
题目:钓鱼岗位有N(5<=N<>=60),钓鱼人数P(1<=P<=20),总共有3个入口,3个入口位置在不同的钓鱼岗,从入口到达入口对应的钓鱼岗距离为1,从该位置往两边走,能够到达下一个钓鱼岗,距离也为1。现在每个入口有一定的人排队,求出所有入口处的人全部到达钓鱼岗最小的距离。每个钓鱼岗只能有一个人。
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
//先左还是先右对结果是有影响的,所以两次情况都要考虑到
public class Test32_1216_diaoyu {
static int roomNum;// 港口的数量
static int[] fishRoom;// 钓鱼港口数组
static int[] theDoor = new int[3];// 入口的位置
static int[] people;// 入口对应的人数
static int step1 = 0;// 优先放右边的步数
static int step2 = 0;// 优先放左边的步数
static int minStep = 1000000;// 最小的步数
public static void main(String[] args) throws FileNotFoundException {
long s = System.currentTimeMillis();
Scanner in = new Scanner(new FileInputStream("D:\\test\\Test1216_diaoyu.txt"));
while (in.hasNext()) {
roomNum = in.nextInt();
fishRoom = new int[roomNum];
people = new int[roomNum];
for (int i = 0; i < 3; i++) {
int ind = in.nextInt() - 1;
theDoor[i] = ind;
people[ind] = in.nextInt();
}
// 初始化
minStep = 1000000;
// 调用全排列DFS
DFS(theDoor, 0, theDoor.length - 1);
System.out.println(minStep);
}
// 程序运行时间
long e = System.currentTimeMillis();
System.out.println(e - s + "MS");
}
// 全排列入口的开放顺序
public static void DFS(int[] theDoor, int start, int end) {
// 迭代结束条件
if (start == end) {// 出口--插入怎样往钓鱼港口放人的函数
// 初始化港口数组(0代表没人,1代表已经有人)
fishRoom = new int[roomNum];
step1 = 0;// 初始化步数
// 按照入口开放顺序放人(优先往右边放)
goFishing1(theDoor);
fishRoom = new int[roomNum];
step2 = 0;// 初始化步数
// 优先往右边放
goFishing2(theDoor);
// 找出step1和step2中较小的一个
int min = step1 > step2 ? step2 : step1;
// 更新最小步数
if (min < minStep) {
minStep = min;
}
} else {
// 入口开放顺序的全排列迭代体
for (int i = start; i <= end; i++) {
int temp = theDoor[start];
theDoor[start] = theDoor[i];
theDoor[i] = temp;
DFS(theDoor, start + 1, end);
temp = theDoor[start];
theDoor[start] = theDoor[i];
theDoor[i] = temp;
}
}
}
/*
* ---以下为模拟入口放人各种情况。debug了好长时间,仍然认为不是最简单的办法
*/
// 按照入口开放顺序放人(优先往右边放)
public static void goFishing1(int[] theDoor) {
for (int i = 0; i < 3; i++) {// 遍历三个入口
int doorNum = theDoor[i];// 该入口的位置
int perNum = people[doorNum];// 该入口的人数
letGo1(doorNum, perNum, 1, doorNum);
}
}
// 按照入口开放顺序放人(优先往左边放)
public static void goFishing2(int[] theDoor) {
for (int i = 0; i < 3; i++) {// 遍历三个入口
int doorNum = theDoor[i];// 该入口的位置
int perNum = people[doorNum];// 该入口的人数
letGo2(doorNum, perNum, 1, doorNum);
}
}
// 将该入口的人放去港口(DFS先右再左)
// temp为判断往右还是往左放的标志位;stLen为入口的位置,用来计算步数用
public static void letGo1(int doorNum, int perNum, int temp, int stLen) {
if (perNum != 0) {
if (doorNum >= 0 && doorNum < roomNum) {
if (fishRoom[doorNum] == 0) {
fishRoom[doorNum] = 1;
int index = (doorNum - stLen) > 0 ? (doorNum - stLen + 1) : (stLen - doorNum + 1);// 每放一个人的步数
step1 = step1 + index;// 累计步数
perNum--;// 等待人数减少
// doorNum <roomNum- 1防止数组越界
if (temp % 2 == 1 && doorNum < roomNum) {
letGo1(doorNum + temp, perNum, temp + 1, stLen);
} else {
letGo1(doorNum - temp, perNum, temp + 1, stLen);
}
} else {// 如果最近的钓鱼口已经有人在,接着往下找
if (temp % 2 == 1 && doorNum < roomNum) {
letGo1(doorNum + temp, perNum, temp + 1, stLen);
} else {
letGo1(doorNum - temp, perNum, temp + 1, stLen);
}
}
} else {
if (doorNum < 0) {// 如果超出数组范围,分情况考虑
letGo1(doorNum + temp, perNum, temp + 1, stLen);
} else {
letGo1(doorNum - temp, perNum, temp + 1, stLen);
}
}
}
}
// 将该入口的人放去港口(DFS先左再右)
// temp为判断往右还是往左放的标志位;stLen为入口的位置,用来计算步数用
public static void letGo2(int doorNum, int perNum, int temp, int stLen) {
if (perNum != 0) {
if (doorNum >= 0 && doorNum < roomNum) {// 如果在数组范围内
if (fishRoom[doorNum] == 0) {
fishRoom[doorNum] = 1;
int index = (doorNum - stLen) > 0 ? (doorNum - stLen + 1) : (stLen - doorNum + 1);
step2 = step2 + index;
perNum--;
if (temp % 2 == 0 && doorNum < roomNum - 1) {
letGo2(doorNum + temp, perNum, temp + 1, stLen);
} else {
letGo2(doorNum - temp, perNum, temp + 1, stLen);
}
} else {// 如果最近的钓鱼口已经有人在,接着往下找
if (temp % 2 == 0 && doorNum < roomNum - 1) {
letGo2(doorNum + temp, perNum, temp + 1, stLen);
} else {
letGo2(doorNum - temp, perNum, temp + 1, stLen);
}
}
} else {// 如果超出数组范围,分情况考虑
if (doorNum < 0) {
letGo2(doorNum + temp, perNum, temp + 1, stLen);
} else {
letGo2(doorNum - temp, perNum, temp + 1, stLen);
}
}
}
}
}
case:
10
2 4
3 2
10 3
20
3 10
6 2
13 2
11
10 6
3 3
6 2
10
10 3
1 3
5 3
10
4 5
6 2
10 2
2 4
3 2
10 3
20
3 10
6 2
13 2
11
10 6
3 3
6 2
10
10 3
1 3
5 3
10
4 5
6 2
10 2