题目回忆:
具体比较复杂,我按自己的理解(尚未知对否)简化为,将m x n数组,也就是田地,横竖各切三刀划分为16个分块,求如何切这6刀使得划分后的16块田地中最小价值的分块价值最大化,即最大化最小值问题。
解题思路:
感觉应该是个动态规划问题,奈何不知如何解答(鄙人算法特别差),只能用暴力法解决,在这里也就是穷举法进行统计比对产生最优解。
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class Main {
public static void main(String[] args) {
//田地价值,记为m x n数组,这里为实验数据
int[][] land = {{3,3,4,4,4},
{2,4,3,2,6},
{4,4,5,3,3},
{3,5,2,2,5},
{3,5,2,2,5},
{3,5,2,2,5},
{3,5,2,2,5},
{3,5,2,2,5}};
Main main = new Main();
main.distributeLandTo16(land);
}
/**
* 分成16块田地,横竖各切3刀
* @param arr
* @return
*/
void distributeLandTo16(int[][] land) {
int m = land.length, n = land[0].length;
Map<String,Integer> allValues = new HashMap<String,Integer>(); //存放所有方案的各田地分块最小价值
// 这里分成16块田地,横竖各切3刀,记x1 x2 x3 y1 y2 y3
// 若第一横刀 x1 切 land[0] 和 land[1] 之间,则记 x1 值为0,以此类推,所以有范围如下:
// 0 <= x1 < x2 < x3 < m-1,0 <= y1 < y2 < y3 < n-1
int[] x = new int[5], y = new int[5]; //用数组存储,方便循环
x[0] = y[0] = -1;
x[4] = m-1;
y[4] = n-1;
//穷举暴力法
for (x[1] = 0; x[1] < m-3; x[1]++) {
for (x[2] = x[1]+1; x[2] < m-2; x[2]++) {
for (x[3] = x[2]+1; x[3] < m-1; x[3]++) {
for (y[1] = 0; y[1] < n-3; y[1]++) {
for (y[2] = y[1]+1; y[2] < n-2; y[2]++) {
for (y[3] = y[2]+1; y[3] < n-1; y[3]++) {
int[] values = new int[16]; //存放该种分田方法的16个分块的价值
int cnt = 0;
//计算每个田地分块的总价值,共16块
for (int k = 0; k < 4; k ++) {
for (int l = 0; l < 4; l ++) {
//计算单个田地分块的价值
for (int p = x[k]+1; p <= x[k+1]; p++){
for (int q = y[l]+1; q <= y[l+1]; q++) {
values[cnt] += land[p][q];
}
}
cnt++; //已计算完一个田地分块的价值
}
}
//存储具体分地方案,比如“012 134”代表x1=0, x1=1, x2=2, y1=1, y2=3, y3=4
StringBuilder flag = new StringBuilder();
for(int k = 1; k <= 3; k++) {
flag.append(x[k]);
}
flag.append(" ");
for(int k = 1; k <= 3; k++) {
flag.append(y[k]);
}
allValues.put(flag.toString(), getMin(values));
}
}
}
}
}
}
//求最小值最大化的方案,在最小值集合中求得最大值
Iterator it = allValues.keySet().iterator();
String maxKey = "";
int max = 0;
while (it.hasNext()) {
String str = (String) it.next();
if (max < allValues.get(str)) {
max = allValues.get(str);
maxKey = str;
}
}
System.out.println("最大化的最小值,即牛牛能得到的最大价值田地价值为:" + max);
System.out.println("分割方式为:" + maxKey);
}
/**
* 求arr数组中最小值
* @param arr
* @return
*/
Integer getMin(int [] arr) {
int min = arr[0];
for (int num : arr) {
if (min > num)
min = num;
}
return min;
}
}