1. 程式人生 > >經典演算法之博弈論 取球博弈

經典演算法之博弈論 取球博弈

問題描述:

取球博弈.局面上有一堆球,二人博弈,每人一次只能取1,3,7或者8個球.要求輸出局面有n個球時的勝負情況.

解題思路:

這裡我提供兩種題解,一種是純遞迴求解,但純遞迴CPU消耗過大,後面我還會提供動態規劃+快取的題解方法.

實現方式一:

*純遞迴解題, 由於純遞迴對CPU消耗過大,這裡我以1到50個球的局面情況為例

public class Main {
	public static void main(String[] args) {
		for (int i = 1; i <= 50; i++) {    //i為球的總數
			System.out.println(i + ": " + fun(i));   //true為我方必贏 false為必輸
		}
	}

	public static boolean fun(int n) {    //n為局面所剩的球數
		if (n == 0) return true;
		
		if (n > 1 && fun(n - 1) == false) return true;
		if (n > 3 && fun(n - 3) == false) return true;
		if (n > 7 && fun(n - 7) == false) return true;
		if (n > 8 && fun(n - 8) == false) return true;
		return false;
	}
}
github:https://github.com/striner/javaCode/blob/master/Take%20The%20Ball%20(Recursive)

編譯執行:


實現方式二:

*這裡我用動態規劃解決取球問題,由於遞迴時許多程式碼的重複運算嚴重造成了資源的浪費,故需將進行過運算的結果快取起來.

快取有很多實現方式,借用陣列或者Map都可以實現,這裡我以Map為例.

n個球,贏則true,輸則false

ps: 我測試資料時偷懶未使用Scanner類輸入資料,emmm...大家別學我...

程式碼如下:

public class Main {
	static Map<Integer, Boolean> map = new HashMap<>();
	public static void main(String[] args) {
		map.put(0, true);
		System.out.println(fun(1000));
	}

	public static boolean fun(int n) {
		
		if (map.get(n) != null) return map.get(n);
		
		Boolean b = false;
		if (n > 1 && fun(n - 1) == false) b = true;
		if (n > 3 && fun(n - 3) == false) b = true;
		if (n > 7 && fun(n - 7) == false) b = true;
		if (n > 8 && fun(n - 8) == false) b = true;
		
		map.put(n, b);
		return b;
	}
}

github:https://github.com/striner/javaCode/blob/master/Take%20The%20Ball(Dynamic%20Programming)

編譯執行: