A*算法野人传教士问题java
时间: 2023-06-24 20:08:45 浏览: 75
传教士和野人问题(MC问题)的A*算法实现
5星 · 资源好评率100%
下面是使用A*算法解决野人传教士问题的Java代码示例:
```java
import java.util.*;
public class AStarSearch {
private static final int MAX_STATE_SPACE = 100000;
private static final int MAX_PATH_COST = 100000;
private static final int NUM_MISSIONARIES = 3;
private static final int NUM_CANNIBALS = 3;
// State representation of a node
static class Node {
int[] state = new int[2 * NUM_MISSIONARIES + 2];
int pathCost;
int heuristicCost;
Node parent;
public Node(int[] state, int pathCost, int heuristicCost, Node parent) {
this.state = state;
this.pathCost = pathCost;
this.heuristicCost = heuristicCost;
this.parent = parent;
}
public boolean isGoalState() {
return state[0] == 0 && state[1] == 0;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Node) {
Node node = (Node) obj;
return Arrays.equals(state, node.state);
}
return false;
}
@Override
public int hashCode() {
return Arrays.hashCode(state);
}
@Override
public String toString() {
return Arrays.toString(state);
}
}
// Heuristic function
private static int calculateHeuristic(Node node) {
int numMissionariesLeft = node.state[0];
int numCannibalsLeft = node.state[1];
int numMissionariesRight = NUM_MISSIONARIES - numMissionariesLeft;
int numCannibalsRight = NUM_CANNIBALS - numCannibalsLeft;
int heuristicCost = (numMissionariesLeft + numCannibalsLeft - 2) / 2;
if (numMissionariesLeft < numCannibalsLeft || numMissionariesRight < numCannibalsRight) {
heuristicCost += MAX_PATH_COST;
}
return heuristicCost;
}
// Successor function
private static List<Node> generateSuccessors(Node node) {
List<Node> successors = new ArrayList<>();
int[] state = node.state.clone();
int pathCost = node.pathCost + 1;
int numMissionariesLeft = state[0];
int numCannibalsLeft = state[1];
int boatPosition = state[2];
int numMissionariesRight = NUM_MISSIONARIES - numMissionariesLeft;
int numCannibalsRight = NUM_CANNIBALS - numCannibalsLeft;
if (boatPosition == 0) {
// Move one missionary to right
if (numMissionariesLeft > 0) {
state[0] = numMissionariesLeft - 1;
state[2] = 1;
state[3] = numMissionariesRight + 1;
state[4] = numCannibalsRight;
if (isValidState(state)) {
successors.add(new Node(state, pathCost, calculateHeuristic(new Node(state, 0, 0, null)), node));
}
state = node.state.clone();
}
// Move two missionaries to right
if (numMissionariesLeft > 1) {
state[0] = numMissionariesLeft - 2;
state[2] = 1;
state[3] = numMissionariesRight + 2;
state[4] = numCannibalsRight;
if (isValidState(state)) {
successors.add(new Node(state, pathCost, calculateHeuristic(new Node(state, 0, 0, null)), node));
}
state = node.state.clone();
}
// Move one cannibal to right
if (numCannibalsLeft > 0) {
state[1] = numCannibalsLeft - 1;
state[2] = 1;
state[3] = numMissionariesRight;
state[4] = numCannibalsRight + 1;
if (isValidState(state)) {
successors.add(new Node(state, pathCost, calculateHeuristic(new Node(state, 0, 0, null)), node));
}
state = node.state.clone();
}
// Move one missionary and one cannibal to right
if (numMissionariesLeft > 0 && numCannibalsLeft > 0) {
state[0] = numMissionariesLeft - 1;
state[1] = numCannibalsLeft - 1;
state[2] = 1;
state[3] = numMissionariesRight + 1;
state[4] = numCannibalsRight + 1;
if (isValidState(state)) {
successors.add(new Node(state, pathCost, calculateHeuristic(new Node(state, 0, 0, null)), node));
}
state = node.state.clone();
}
// Move one cannibal to right
if (numCannibalsLeft > 1) {
state[1] = numCannibalsLeft - 2;
state[2] = 1;
state[3] = numMissionariesRight;
state[4] = numCannibalsRight + 2;
if (isValidState(state)) {
successors.add(new Node(state, pathCost, calculateHeuristic(new Node(state, 0, 0, null)), node));
}
}
} else {
// Move one missionary to left
if (numMissionariesRight > 0) {
state[0] = numMissionariesLeft + 1;
state[2] = 0;
state[3] = numMissionariesRight - 1;
state[4] = numCannibalsRight;
if (isValidState(state)) {
successors.add(new Node(state, pathCost, calculateHeuristic(new Node(state, 0, 0, null)), node));
}
state = node.state.clone();
}
// Move two missionaries to left
if (numMissionariesRight > 1) {
state[0] = numMissionariesLeft + 2;
state[2] = 0;
state[3] = numMissionariesRight - 2;
state[4] = numCannibalsRight;
if (isValidState(state)) {
successors.add(new Node(state, pathCost, calculateHeuristic(new Node(state, 0, 0, null)), node));
}
state = node.state.clone();
}
// Move one cannibal to left
if (numCannibalsRight > 0) {
state[1] = numCannibalsLeft + 1;
state[2] = 0;
state[3] = numMissionariesRight;
state[4] = numCannibalsRight - 1;
if (isValidState(state)) {
successors.add(new Node(state, pathCost, calculateHeuristic(new Node(state, 0, 0, null)), node));
}
state = node.state.clone();
}
// Move one missionary and one cannibal to left
if (numMissionariesRight > 0 && numCannibalsRight > 0) {
state[0] = numMissionariesLeft + 1;
state[1] = numCannibalsLeft + 1;
state[2] = 0;
state[3] = numMissionariesRight - 1;
state[4] = numCannibalsRight - 1;
if (isValidState(state)) {
successors.add(new Node(state, pathCost, calculateHeuristic(new Node(state, 0, 0, null)), node));
}
state = node.state.clone();
}
// Move one cannibal to left
if (numCannibalsRight > 1) {
state[1] = numCannibalsLeft + 2;
state[2] = 0;
state[3] = numMissionariesRight;
state[4] = numCannibalsRight - 2;
if (isValidState(state)) {
successors.add(new Node(state, pathCost, calculateHeuristic(new Node(state, 0, 0, null)), node));
}
}
}
return successors;
}
// Check if a state is valid
private static boolean isValidState(int[] state) {
int numMissionariesLeft = state[0];
int numCannibalsLeft = state[1];
int boatPosition = state[2];
int numMissionariesRight = NUM_MISSIONARIES - numMissionariesLeft;
int numCannibalsRight = NUM_CANNIBALS - numCannibalsLeft;
if (numMissionariesLeft > NUM_MISSIONARIES || numMissionariesRight > NUM_MISSIONARIES ||
numCannibalsLeft > NUM_CANNIBALS || numCannibalsRight > NUM_CANNIBALS ||
numMissionariesLeft < 0 || numMissionariesRight < 0 || numCannibalsLeft < 0 ||
numCannibalsRight < 0 || (numMissionariesLeft > 0 && numMissionariesLeft < numCannibalsLeft) ||
(numMissionariesRight > 0 && numMissionariesRight < numCannibalsRight)) {
return false;
}
return true;
}
// A* search
public static List<Node> aStarSearch() {
Node root = new Node(new int[]{NUM_MISSIONARIES, NUM_CANNIBALS, 0, 0, 0}, 0, 0, null);
PriorityQueue<Node> frontier = new PriorityQueue<>(MAX_STATE_SPACE, Comparator.comparingInt(o -> o.pathCost + o.heuristicCost));
Set<Node> explored = new HashSet<>();
frontier.add(root);
while (!frontier.isEmpty()) {
Node node = frontier.poll();
if (node.isGoalState()) {
List<Node> path = new ArrayList<>();
while (node != null) {
path.add(node);
node = node.parent;
}
Collections.reverse(path);
return path;
}
explored.add(node);
List<Node> successors = generateSuccessors(node);
for (Node successor : successors) {
if (!frontier.contains(successor) && !explored.contains(successor)) {
frontier.add(successor);
} else if (frontier.contains(successor)) {
Iterator<Node> iterator = frontier.iterator();
while (iterator.hasNext()) {
Node existingNode = iterator.next();
if (existingNode.equals(successor) && existingNode.pathCost > successor.pathCost) {
iterator.remove();
frontier.add(successor);
break;
}
}
} else if (explored.contains(successor)) {
Iterator<Node> iterator = explored.iterator();
while (iterator.hasNext()) {
Node existingNode = iterator.next();
if (existingNode.equals(successor) && existingNode.pathCost > successor.pathCost) {
iterator.remove();
frontier.add(successor);
break;
}
}
}
}
}
return null;
}
public static void main(String[] args) {
List<Node> path = aStarSearch();
if (path == null) {
System.out.println("No solution found!");
} else {
System.out.println("Optimal solution found with cost " + path.get(path.size() - 1).pathCost);
for (Node node : path) {
System.out.println(Arrays.toString(node.state));
}
}
}
}
```
在这个示例中,我们使用了一个自定义的`Node`类来表示状态空间中的一个节点。每个节点都有一个状态表示、路径成本、启发式成本和一个父节点。我们还定义了一个`calculateHeuristic`方法来计算启发式成本,一个`generateSuccessors`方法来生成一个节点的后继节点,一个`isValidState`方法来检查一个状态是否有效,以及一个`aStarSearch`方法来执行A*搜索。
在主方法中,我们调用`aStarSearch`方法来获取最优解路径,并打印出每个节点的状态表示。如果无法找到解决方案,则打印一条消息表示无法找到解决方案。
阅读全文