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);

	}

}

运行截图

在这里插入图片描述

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