JAVA實現多邊形遊戲

5、實驗四多邊形遊戲

實驗內容

按照要求輸入多邊形的邊和頂點,遊戲第一步: 刪除一條邊, 隨後的n-1步按以下方式操作:
1)選擇一條邊E以及由E連接着的2個頂點v1和v2
2)用一個新的頂點取代邊E以及由E連着的2個頂點v1和v2。將由頂點v1和v2的整數值通過邊E上的運算得到的結果賦予新頂點。直到最後,所有邊被刪除,確認使結果達到最大值的刪除方式和最大值。

解題思路

通過所給的多邊形,從頂點i(1<=i<=n)開始,長度爲j(鏈中有j個頂點)的順時針鏈p(i,j)可表示爲v[i],op[i+1],…,v[i+j-1],如果這條鏈的最後一次合併運算在op[i+s]處發生(1<=s<=j-1),則可在op[i+s]處將鏈分割爲兩個子鏈p(i,s)和p(i+s,j-s)。若最優合併在op[i+s]處將p(i,j)分爲兩個長度小於j的子鏈的最大值和最小值均可計算出。

源代碼

package d多邊形遊戲;

import java.util.HashMap;
import java.util.Scanner;

public class PolygonGame {

	public static void main(String[] args) {
		System.out.println("請輸入邊(點)的個數:");
		Scanner scanner = new Scanner(System.in);

		int n = scanner.nextInt();
		long[][][] m = new long[n + 1][n + 1][2];
		char[] op = new char[n + 1];
		int[] v = new int[n + 1];
		System.out.print("\n");
		System.out.println("請輸入邊和點:");
		for (int i = 1; i <= n; i++) { // i從1開始
			op[i] = scanner.next().charAt(0);
			v[i] = scanner.nextInt();
		}

		PolygonGame ploygonAgent = new PolygonGame(n, m, op, v);

		for (int i = 1; i <= n; i++) { // 初始化m[i][j][0]和m[i][j][1]的第一列
			m[i][1][0] = m[i][1][1] = v[i];
		}

		//執行函數
		ploygonAgent.polyMax();

	}

	private int n; // 多邊形邊數
	private char[] op; // 每條邊的對應的操作(從1開始計數)
	private long[][][] m; // m[i][n][1]:代表一開始刪除第i條邊,長度爲n的鏈(包含n個頂點),所能得到的最大值
							// m[i][n][0]:代表一開始刪除第i條邊,長度爲n的鏈,所能得到的最小值
	private int[][][] cut; // cut[i][j][0];表示m[i][j][0]這條鏈的達到最小數值的時候斷開的位置
							// cut[i][j][1]: 表示m[i][j][1]這條鏈的達到最大數值的時候斷開的位置
	private int firstDelEdge; // 記錄最優情況下,第1條刪除的邊
	private long bestScore; // 記錄最優得分

	// 初始化
	public PolygonGame(int n, long[][][] m, char[] op, int[] v) {
		this.n = n;
		this.m = m;
		this.op = op;
		this.cut = new int[n + 1][n + 1][2];
	}

	private HashMap<String, Long> minMax(int i, int s, int j, HashMap<String, Long> resMap) {
		int r = (i + s - 1) % n + 1;
		long a = m[i][s][0], b = m[i][s][1], c = m[r][j - s][0], d = m[r][j - s][1];
		if (op[r] == '+') {
			resMap.put("minf", a + c);
			resMap.put("maxf", b + d);
		} else {
			long[] e = new long[] { 0, a * c, a * d, b * c, b * d };
			long minf = e[1], maxf = e[1];
			for (int k = 2; k < 5; k++) {
				if (minf > e[k])
					minf = e[k];
				if (maxf < e[k])
					maxf = e[k];
			}
			resMap.put("minf", minf);
			resMap.put("maxf", maxf);
		}
		return resMap;
	}

	/**
	 * @see 把斷點填入cut[i][j][0]和cut[i][j][1],並把最值並把最值填入m[i][j][0] 和 m[i][j][1]
	 */
	private void polyMax() {

		// 1 填表 m[i][j][0] 和 m[i][j][1] 和 cut[i][j][0] 和 cut[i][j][1]
		HashMap<String, Long> resMap = new HashMap<>();
		for (int j = 2; j <= n; j++) { // 鏈的長度
			for (int i = 1; i <= n; i++) { // 一開始斷開第i條邊的時候
				m[i][j][0] = Long.MAX_VALUE;
				m[i][j][1] = Long.MIN_VALUE;
				for (int s = 1; s < j; s++) { // 斷開的位置
					resMap = this.minMax(i, s, j, resMap);
					if (m[i][j][0] > resMap.get("minf")) {
						m[i][j][0] = resMap.get("minf");
						cut[i][j][0] = s; // 記錄該鏈取得最小值的斷點
					}
					if (m[i][j][1] < resMap.get("maxf")) {
						m[i][j][1] = resMap.get("maxf");
						cut[i][j][1] = s; // 記錄該鏈取得最大值的斷點
					}
				}
			}
		}

		// 2 根據表m算出第一次斷開哪裏的時候的數值最大,並輸出一些相關數據
		bestScore = m[1][n][1];
		firstDelEdge = 1; // 一開始斷開的邊,初始化爲第一條邊
		for (int i = 2; i <= n; i++) {
			if (bestScore < m[i][n][1]) {
				bestScore = m[i][n][1];
				firstDelEdge = i; // 如果一開始斷開第i邊有更優的結果,則更新
			}
		}

		// 3輸出m矩陣的最小值和最大值
		System.out.println();
		System.out.println("最小值" + "\\" + "最大值");
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				System.out.print(m[i][j][0] + "\\" + m[i][j][1] + "\t");
			}
			System.out.println();

		}

		// 4輸出s矩陣的最大值位置
		System.out.println();
		System.out.println("給出最大值位置");
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				System.out.print(cut[i][j][1] + "\t");
			}
			System.out.println();

		}

		System.out.print("\n");
		System.out.println("多邊形遊戲首次刪除第" + firstDelEdge + "次條邊,結果爲:" + bestScore);

	}

}

運行截圖

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章