CSP 202104-2 邻域均值 java 满分题解

CSP 202104-2 邻域均值 java 满分题解

代码

import java.util.Arrays;
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		/*
		 *  对n*n矩阵的 每个点 计算 r范围内和 与 t之间的关系
		 *  对于边界不全 为了方便计算 可对矩阵扩宽为 (n+2r)*(n+2r)的矩阵 其中补白值为t(求和与 定值大小判断)
		 *  其中 为了方便计算出每个 为(2r+1)矩阵块 的和(同全1矩阵之间的卷积)
		 *  可进行 行/列 之间的缩小计算:
		 *  	可 先对于每行 进行 2r+1 滑动条和的缩小:进而此时(n+2r)*n 的行列式 每个值为 以该端点的行和
		 *  		其次 对于列 在上述基础上进行相同操作 此时 n*n 的矩阵 每个值为该端点的行列之和
		 *  即可遍历n*n矩阵 对每个点进行判断即可
		 */
		int n, L, r, t;
		Scanner scanner = new Scanner(System.in);
		n = scanner.nextInt();
		L = scanner.nextInt();
		r = scanner.nextInt();
		t = scanner.nextInt();
		int[][] a = new int[n + 2 * r][n + 2 * r];// 原始矩阵 进行 补白 补充值为t
		long sum = 0;//计算总和
		for (int i = 0; i < n + 2 * r; i++) {
			for (int j = 0; j < n + 2 * r; j++) {
				if (i >= r && i <= r + n - 1 && j >= r && j <= r + n - 1) {
					a[i][j] = scanner.nextInt();//非补值直接放入
					sum += a[i][j];
				} else {
					a[i][j] = t;// 补入位置 补t 计算时将统一计算 均为全矩阵
				}
			}
		}
		if (n - 1 <= r) {// 判断矩阵只为一个 直接判断是否满足即可(和/平均值 都为一个)
			//如果满足 则都满足 反之 则不然
			if (sum <= t * n * n) {
				System.out.print(n * n);
			} else {
				System.out.print(0);
			}
			scanner.close();
			return;
		}
		
		int sum_tmp = 0;
		
		// 先进行 列上的聚合 对每行进行滚动 2r+1 聚合 行数不变 列数成n
		int[][] b = new int[n + 2 * r][n];
		for (int i = 0; i < n + 2 * r; i++) {
			sum_tmp = 0;
			// 先计算每行的前缀和数组
			int[] tmp = new int[n + 2 * r];
			for (int j = 0; j < n + 2 * r; j++) {
				sum_tmp += a[i][j];
				tmp[j] = sum_tmp;
			}
			// 计算出 滚动结果数组 并放入
			b[i][0] = tmp[2 * r];
			for (int j = 1; j <= n - 1; j++) {
				b[i][j] = tmp[2 * r + j] - tmp[j - 1];
			}
		}
		
		// 再对上述已经 列聚合的数组 进行每列进行 2r+1 滚动 得到n*n 矩阵 矩阵的每一个值均为每个完全矩阵的sum
		int[][] c = new int[n][n];
		for (int i = 0; i < n; i++) {
			sum_tmp = 0;
			for(int j=0;j<2*r+1;j++) {
				sum_tmp+=b[j][i];
			}
			for(int j = 0;j<n;j++) {
				c[j][i] = sum_tmp;
				if(j==n-1) {
					break;
				}
				sum_tmp = sum_tmp - b[j][i] + b[2*r+1+j][i];
			}
//			
//			sum_tmp = 0;
//			int[] tmp = new int[n + 2 * r];
//			for (int j = 0; j < n + 2 * r; j++) {
//				sum_tmp += b[j][i];
//				tmp[j] = sum_tmp;
//			}
//			c[0][i] = tmp[2 * r];
//			for (int j = 1; j <= n - 1; j++) {
//				c[j][i] = tmp[2 * r + j] - tmp[j - 1];
//			}
		}
		
		
		int count = 0;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				//求其和 t*(2r+1)^2 之间的关系 即为判断每个点邻域的均值是否小于t
				if (c[i][j] <= Math.pow(2 * r + 1, 2) * t) {
					count++;
				}
			}
		}
//
//		System.out.println();
//		for (int i = 0; i < n + 2 * r; i++) {
//			for (int j = 0; j < n + 2 * r; j++) {
//				System.out.print(a[i][j] + " ");
//			}
//			System.out.print("\n");
//		}
//
//		System.out.println();
//		for (int i = 0; i < n + 2 * r; i++) {
//			for (int j = 0; j < n; j++) {
//				System.out.print(b[i][j] + " ");
//			}
//			System.out.print("\n");
//		}
//
//		System.out.println();
//		for (int i = 0; i < n; i++) {
//			for (int j = 0; j < n; j++) {
//				System.out.print(c[i][j] + " ");
//			}
//			System.out.print("\n");
//		}

		System.out.print(count);
		scanner.close();
	}

}

总结

1、当暴力明显无法通过全部数据时 需要使用 更好的方法减低时间复杂度
2、对于特殊的计算情况 思考能否人为转化为 统一计算方式 进而可以统一计算方法
3、思考时间复杂度主要集中的地方 如何优化
4、矩阵的计算方式 往往可以先考虑 行/列 进行 逐一计算/优化
5、本题 使用了 卷积神经网络的经典 方法 补0 其次对于每个t矩阵和 可通过行、列累计和 进而避免每个矩阵进行O(n^2)计算量
6、对于:n个数的一维数组,m为滚动窗口,可使用 对每次变化进行加减的方式进行移动计算m个连续和 或者 使用 前缀和数组 直接遍历计算出即可 均为O(n)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值