JAVA实现矩阵与两倍子矩阵重量的差值最小 蓝桥杯模拟

JAVA实现矩阵与两倍子矩阵重量的差值最小

问题描述
  给定一个矩阵 M,由 n 行 m 列组成,第 i 行第 j 列值为 M[i][j]。定义矩阵 M 的重量为矩阵中所有元素的和,几位weight(M)请找到矩阵左上角的一个子矩阵S(矩阵的前 r 行中的前 c 列组成),使得这个子矩阵的重量的两倍最接近矩阵 M 重量。即 |2 weight(S)-weight(M)| 最小。如果有多个子矩阵满足条件,请找出面积 r * c 最小的一个。如果仍然有多个子矩阵满足条件,请找出其中 r 最小的一个。
  
输入格式
  输入第一行包含两个整数 n, m,表示矩阵的大小。
  接下来 n 行,每行 m 个整数,表示给定的矩阵M。
输出格式
  输出一行,包含两个整数 r, c,表示子矩阵为矩阵 M 的前 r 行中的前 c 列。
样例输入
3 4
3 0 1 1
1 0 1 1
1 1 -2 4
样例输出
2 3
数据规模和约定
  对于 30% 的评测用例,1 <= n, m <= 20, -10 <= M[i][j] <= 10。
  对于 50% 的评测用例,1 <= n, m <= 100, -100 <= M[i][j] <= 100。
  对于所有评测用例,1 <= n, m <= 1000, -1000 <= M[i][j] <= 1000。
  
 
思路:获取矩阵左上角每个子矩阵的重量 * 2 - 矩阵的重量,再用Math工具类的abs方法取绝对值,记录下每次的差值和i,j(i*j为子矩阵的面积)当最小差值相等的时候在比较面积,保留面积小的子矩阵;而面积也相等时,其中取 r 最小的一个,因为是从上到下枚举的,r 是从小到大的,所以最小值相等,面积也相等的情况在后面出现的话 r 是一定大于 c 的,只需保留前面的结果就是题目所求。

用动态规划推导每个子矩阵的重量:
在这里插入图片描述

public class Main {

	
	static int n,m,total=0;
	static int[][] M;
	static int r,c,d=Integer.MAX_VALUE;//r为长,c为宽,d为子矩阵面积
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		 n = sc.nextInt();
		 m = sc.nextInt();
		 M = new int[n][m];
		
		for(int i=0;i<n;i++){
			for (int j = 0; j < m; j++) {
				
				M[i][j]=sc.nextInt();
				//矩阵的总重量
				total+=M[i][j];
			}
		}
		//将原数组扩大一圈,用来保存每个子矩阵的重量
		int[][] dp=new int[n+1][m+1];
		for(int i=1;i<=n;i++){
			for (int j = 1; j <=m; j++) {
				//状态转移方程,dp[i][j]所在的大的矩阵等于dp[i-1][j]上面的小矩阵加上dp[i][j-1]左边的小矩阵再减去dp[i-1][j-1]重复的小矩阵再加上M[i-1][j-1]的值
				dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+M[i-1][j-1];
				//检查是否符合
				check(dp[i][j],i,j);
					
				}
			}
		
	System.out.println(r+" "+c);

}
	private static void check(int x, int i, int j) {
		//因为是从上到下遍历的,所以差值最小,面积也相同时,r>c的 
		if(Math.abs(2*x-total)<d || Math.abs(2*x-total)==d && i*j<r*c){
			r=i;
			c=j;
			d=Math.abs(2*x-total);
		}
	}
}

动态规划:后面的结果需要利用前面的结果推导出来,子问题的重叠

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值