package srm646; import java.util.Comparator; import java.util.HashSet; import java.util.PriorityQueue; import java.util.Set; public class TheGridDivTwo { //<1>state的比较函数,是"大于>"即大的在前面,属于降序排序 //<2>比较函数在 score-step,这个是启发是搜索策略,可以让搜索,尽量向右搜索,而不是向左,即有一定的方向性。 //当然,如果直接基于score排序,这也是可以的,但性能应该差一些。 static public class State implements Comparator<State>,Comparable<State> { public State() { } public State(int x, int y, int score) { this.x = x; this.y = y; this.score = score; } int x; int y; int score; int step; @Override public int compare(State o1, State o2) { // TODO Auto-generated method stub if (o1.score-o1.step < o2.score-o2.step) { return 1; } if (o1.score-o1.step == o2.score-o2.step) { return 0; } return -1; } @Override public String toString(){ return "{"+x+","+y+","+score+","+step+"}"; } @Override public int hashCode() { return x ^ y; } @Override public boolean equals(Object src) { return src != null && src instanceof State && ((State) src).x == x && ((State) src).y == y; } @Override public int compareTo(State o) { if (score -step< o.score-step) { return 1; } if (score-step == o.score-step) { return 0; } return -1; } } public int find(int[] x, int[] y, int k) { int ans = 0; Set<State> blockedMap = new HashSet<State>(); for (int i = 0; i < x.length; i++) { blockedMap.add(new State(x[i], y[i], 0)); } State start = new State(); start.x = 0; start.y = 0; start.score = 0; start.step = 0; State maxState = new State(0, 0, 0); PriorityQueue<State> pq = new PriorityQueue<State>(); Set<State> visited = new HashSet<State>(); pq.add(start); visited.add(start); while (!pq.isEmpty()) { State cur = pq.poll(); if (cur.step > k) { continue; } if (maxState.score < cur.score) { maxState.score = cur.score; maxState.x = cur.x; maxState.y = cur.y; maxState.step = cur.step; } //后面的得分会更小(这个是分支限界,剪枝策略) if(cur.score + k - cur.step <= maxState.score){ continue; } if (cur.step < k) { // [cur.x+1][cur.y+1] State next = null; next = new State(cur.x + 1, cur.y, cur.score + 1); next.step = cur.step + 1; if (!blockedMap.contains(next)) { if (!visited.contains(next)) { pq.add(next); visited.add(next); } } next = new State(cur.x - 1, cur.y, cur.score -1); next.step = cur.step + 1; if (!blockedMap.contains(next)) { if (!visited.contains(next)) { pq.add(next); visited.add(next); } } next = new State(cur.x, cur.y + 1, cur.score); next.step = cur.step + 1; if (!blockedMap.contains(next)) { if (!visited.contains(next)) { pq.add(next); visited.add(next); } } next = new State(cur.x, cur.y - 1, cur.score); next.step = cur.step + 1; if (!blockedMap.contains(next)) { if (!visited.contains(next)) { pq.add(next); visited.add(next); } } } } System.out.println(maxState); ans = maxState.score; return ans; } public static void main(String args[]) { TheGridDivTwo div2= new TheGridDivTwo(); int ans = div2.find(new int[]{1,1,1,1}, new int[]{-2,-1,0,1},4); System.out.println(ans); ans = div2.find(new int[]{1,0,0,-1,-1,-2,-2,-3,-3,-4,-4}, new int[]{0,-1,1,-2,2,-3,3,-4,4,-5,5},47); System.out.println(ans); } }
这是SRM646 的div2 题,刚开始,比较函数写成了<,后修改为降序排列,但没改正确,检查很多遍都没有发现。
这是一个基本的穷举搜索过程,但在brute-force search中可以加入一些策略,比如启发式的(score-step),这个也算A*,再加入一个限界,用于剪枝