alpha-beta剪枝测试题
Java代码:
import java.util.ArrayList; import java.util.Scanner; public class Main { private static ArrayList<String> cutpath = new ArrayList<>(); public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); ArrayList<Node> nodelist = new ArrayList<Node>(); for (int i = 0; i < n; i++) { int id = sc.nextInt(); int val = sc.nextInt(); int pid = sc.nextInt(); Node node = new Node(id, val, pid); if (id == 1) { node.flag = true; } else if (nodelist.get(pid - 1).flag) { node.flag = false; } else { node.flag = true; } nodelist.add(node); if (pid != -1) { nodelist.get(pid - 1).childid.add(id); } } sc.close(); go(nodelist); for (int i = 0; i < nodelist.get(0).childid.size(); i++) { if (nodelist.get(0).val == nodelist.get(nodelist.get(0).childid.get(i) - 1).val) { System.out.println( "1 " + nodelist.get(nodelist.get(0).childid.get(i) - 1).id + " " + nodelist.get(0).val); break; } } for (String s : cutpath) { System.out.println(s); } } public static void go(ArrayList<Node> nodelist) { Node root = nodelist.get(0); dfs(root, nodelist); } public static int dfs(Node node, ArrayList<Node> nodelist) { if (!node.childid.isEmpty()) {// 非叶子结点 if (node.noused) { if (node.flag) { node.val = -999; } else { node.val = 999; } node.noused = false; } int s = node.childid.size(); // 遍历子结点 for (int i = 0; i < s; i++) { /** * 如果是极大结点(flag==true),从子节点获得的值大于兄弟结点,则后续子节点不必再遍历 * 如果是极小结点(flag==false),从子节点获得的值小于兄弟结点,同样剪枝 剪枝即输出该结点与子节点的序号 若是极大结点再输出beta * 极小结点输出arlfa 然后continue; if(cut) { continue; } * */ // 该结点不是根节点 if (node.parentid != -1) { // 该结点无兄弟结点,则与爷结点的兄弟结点相比 int gpid=1; if(node.id>7){ gpid = nodelist.get(nodelist.get(node.parentid - 1).parentid - 1).id; } boolean existgp=false; if (node.id>7 && nodelist.get(node.parentid - 1).childid.size() == 1 && nodelist.get(nodelist.get(gpid-1).parentid-1).childid.get(0)!=gpid) { existgp=true; } // 若是极大结点 if (node.flag) { // 若该结点值大于之前任一兄弟结点,则不必再遍历该结点的子节点 boolean cut = false; for (int j = 0; j < nodelist.get(node.parentid - 1).childid.indexOf(node.id); j++) { if (node.val > nodelist.get(nodelist.get(node.parentid - 1).childid.get(j) - 1).val) { cut = true; break; } } if (existgp && nodelist.get(node.parentid - 1).childid.size() == 1 && nodelist.get(nodelist.get(gpid-1).childid.get(0)-1).id!=gpid) { if(node.val>nodelist.get(nodelist.get(nodelist.get(gpid-1).parentid-1).childid.get(0)-1).val) { cut=true; } } if (cut) { cutpath.add(node.id + " " + node.childid.get(i) + " beta"); continue; } } else { // 若该结点值小于之前任一兄弟结点,则不必再遍历该结点的子节点 boolean cut = false; for (int j = 0; j < nodelist.get(node.parentid - 1).childid.indexOf(node.id); j++) { if (node.val < nodelist.get(nodelist.get(node.parentid - 1).childid.get(j) - 1).val) { cut = true; break; } } if (existgp && nodelist.get(node.parentid - 1).childid.size() == 1 && nodelist.get(nodelist.get(gpid-1).childid.get(0)-1).id!=gpid) { if(node.val<nodelist.get(nodelist.get(nodelist.get(gpid-1).parentid-1).childid.get(0)-1).val) { cut=true; } } if (cut) { cutpath.add(node.id + " " + node.childid.get(i) + " alpha"); continue; } } } int k = dfs(nodelist.get(node.childid.get(i) - 1), nodelist); // 根据从子节点得到的信息,更改该结点的值 if (node.flag) { if (k > node.val) { node.val = k; } } else { if (k < node.val) { node.val = k; } } } return node.val; } else {// 叶子结点 return node.val; } } } class Node { public boolean noused = true; public boolean flag; public int parentid; public int id; public int val; public ArrayList<Integer> childid = new ArrayList<>(); public Node() { } public Node(int id, int val, int pid) { this.id = id; this.val = val; this.parentid = pid; } }
测试样例和输出:
39 1 0 -1 2 0 1 3 0 1 4 0 2 5 0 2 6 0 3 7 0 3 8 0 4 9 0 4 10 0 5 11 0 5 12 0 5 13 0 5 14 0 6 15 0 6 16 0 7 17 0 7 18 0 8 19 5 8 20 -3 9 21 3 9 22 3 10 23 -3 11 24 0 11 25 2 11 26 2 12 27 -3 12 28 0 12 29 -2 13 30 3 13 31 5 14 32 4 14 33 1 14 34 -3 15 35 0 15 36 6 16 37 8 16 38 9 17 39 -3 17 样例输出 1 3 1 9 21 alpha 5 11 beta 5 12 beta 5 13 beta 15 35 alpha 7 17 beta