算法导论—Monge矩阵分析

用java实现了(d)那个算法,贴出来大家给点意见哈:


4-7 Monge矩阵

   一个m x n的实数矩阵A,如果对所有i,j,k和l,1≤ i<k ≤ m和1≤ j<l ≤ n,有

             A[i,j]+A[k,l] ≤ A[i,l]+A[k,j]

   那么,此矩阵A为Monge矩阵。换句话说,每当我们从Monge矩阵中挑出两行与两列,并且考虑行列交叉处的4个元素,左上角与右下角的和小于或等于左下角与右上角元素的和。

a)证明一个矩阵为Monge阵,当且仅当对所有i=1,2,...,m-1和j=1,2,...,n-1,有

             A[i,j]+A[i+1,j+1] ≤ A[i,j+1]+A[i+1,j]

(提示:在当部分,对行、列分别使用归纳法。)

b)下面的矩阵不是Monge阵。改变一个元素,把它变成Monge阵(提示:利用a)的结论)

             37       23       22      32

             21        6       27      10

             53       34       30      31

             32       13        9       6

             43       21       15       8

c) 假设f(i)是第i行包含最左端最小值的列的索引值。证明对任何的m x n Monge矩阵,有f(1) ≤ f(2) ≤...≤ f(m)。

d) 以下是一段关于分治算法的描述,用来计算m x n Monge矩阵A中每一行的最左端最小值:

   构造一个包含所有A的偶数行的子矩阵A'。递归地计算A'中每一行的最左端最小值。然后计算A中奇数行的最左端最小值。

   解释如何能在O(m+n)时间内计算出A的奇数行的最左端最小值?(假设偶数行最左端最小值已知)

e)写出d)部分所描述算法的运行时间的递归式,并证明其解为O(m+nlogm)


package com.yjh.monge;

public class MongeMatrix {

	/**
	 * @param args
	 */

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[][] num = new int[][]{{10, 17, 13, 28, 23}, {17, 22, 16, 29, 23}, {24, 28, 22, 34, 24}, {11, 13, 6, 17, 7}, {45, 44, 32, 37, 23}, {36, 33, 19, 21, 6}, {75, 66, 51, 53, 34}};
		Monge mm = new Monge(num);
		MongeItem[] min = mm.mongeSearchMin(num, 7);
		System.out.println("该Monge矩阵最左端最小值序列是:");
		for(MongeItem i : min)
			System.out.print(i + ", ");
	}
}

//MongeItem类用来表示每行中最左端最小值元素及其列下标
class MongeItem {
	public int index;
	public int value;
	MongeItem(int value, int index) {
		this.index = index;
		this.value = value;
	}
	//定义toString()
	public String toString() {
		return this.value + "";
	}
}

//Monge类用来表示Monge矩阵以及其相关操作
class Monge {
	private int x, y; //mongeArray的行和列
	Monge(int[][] m) {
		x = m.length;
		y = m[0].length;
	}
	//mongeSearchMin()递归的找出最左端最小值序列
	public MongeItem[] mongeSearchMin(int[][] monge1, int m) {
		MongeItem[] min = new MongeItem[m]; //min数组用来存储每一层的最左端最小值序列
		//递归中最低层情况
		if(m == 1) {
			int key1 = monge1[0][0];
			min[0] = new MongeItem(key1 = monge1[0][0], 0);
			for(int i = 0; i < y; i++) {
				if(monge1[0][i] < key1) {
					min[0] = new MongeItem(key1 = monge1[0][i], i);
				}
			}
			return min;
		} else {
			//even[]用来得到该层Monge矩阵的偶数行组成的矩阵A'
			MongeItem even[] = mongeSearchMin(productArray(monge1, m, y), (int)(Math.ceil((double)m/2)));
			int jj = 0; //jj用来定位even[]
			//下面的循环利用A'找出奇数行中的最左端最小值序列放入min[]中
			for(int i = 1; i < monge1.length; i = i + 2, jj++) {
				int key = monge1[i][even[jj].index];
				min[i - 1] = even[jj];
				min[i] = new MongeItem(key = monge1[i][even[jj].index], even[jj].index);
				//这里的try{}catch{}用来排除一个总行数m为偶数时的ArrayIndexOutOfBoundsException异常
				try {
					//这里之所以(jj + 1 >= even.length && j < y)是因为当总行数m为偶数是不能借助even[jj + 1].index,只能循环到最后一列
					for(int j = even[jj].index + 1; (jj + 1 >= even.length && j < y) || j <= even[jj + 1].index; j++) {
						if(monge1[i][j] < key) 
							min[i] = new MongeItem(key = monge1[i][j], j);	
					} 
				} catch(Exception e) {
						e.getStackTrace();
				}
				if(jj < even.length && i + 1 < monge1.length)
					min[i + 1] = even[jj + 1];
			}
			return min;
		}
	}
	
	//用来从矩阵中取出偶数行
	public int[][] productArray(int[][] oldArray, int m, int n) {
		int[][] newArray = new int[(int)(Math.ceil((double)m/2))][n];
		int j = 0;
		for(int i = 0; i < oldArray.length; i=i+2) {
			try {
			newArray[j] = oldArray[i];
			} catch(Exception e) {
				System.out.println();
			}
			j++;
		}
		return newArray;
	}
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值