递归——矩阵归零消减序列和

该博客主要讨论了一个涉及矩阵变换的问题,其中矩阵通过特定的归零和消减过程逐步转化为1*1矩阵。在每次消减前,需要计算a[1][1]的值之和。输入是一个整数n和n个n*n的矩阵,输出是每次消减前a[1][1]的和。示例展示了输入和输出的情况,并提供了一个C++实现的算法来解决这个问题。
摘要由CSDN通过智能技术生成
描述
    给定一个n*n的矩阵(3<=n<=100,元素的值都是非负整数)。通过n-1次实施下述过程,可把这个矩阵转换成一个1*1的矩阵。每次的过程如下:
    首先对矩阵进行归零:即对每一行(或一列)上的所有元素,都在其原来值的基础上减去该行(或列)上的最小值,保证相减后的值仍然是非负整数,且这一行(或列)上至少有一个元素的值为0。
    然后对矩阵进行消减:即把n*n矩阵的第二行和第二列删除(如果二维数组为a[][],则删除的是a[1][1]所在的行和列),使之转换为一个(n-1)*(n-1)的矩阵。
    下一次过程,对生成的(n-1)*(n-1)矩阵实施上述过程。显然,经过n-1次上述过程, n*n的矩阵会被转换为一个1*1的矩阵。
    请求出每次消减前a[1][1]值之和。
关于输入
第一行是一个整数n。
其后是n个n*n的矩阵。
每个矩阵占n行,每行有n个正整数,每个整数间用空格分隔。
关于输出
输出为n行,每行上的整数为对应矩阵归零消减过程中,每次消减前a[1][1]值之和。
例子输入
3

1 2 3

2 3 4

3 4 5

1 2 3

5 4 2

9 4 5

1 2 3

5 4 2

9 5 4

例子输出
0

2

1

#include<iostream>
using namespace std;
int n;
int a[101][101] = {};
int sum = 0;
void f(int x)
{
	if (x == 1) {//进行n-1次操作后返回
		cout << sum << endl;
		return;
	}
	int zero[101] = {};//用以记录已经有0的列
	int MIN = 10000;
	int i, j, col = -1;
	for (i = n - x; i < n; ++i) {//遍历每一行
		for (j = n - x; j < n; ++j) {
			if (a[i][j] < MIN) { //找到最小,并记录列的位置
				MIN = a[i][j]; 
				col = j;
			}
		}
		zero[col] = 1; //标记该列
		for (j = n - x; j < n; ++j) {//依次减去最小值
			a[i][j] -= MIN;
		}
		MIN = 100;//重置MIN!!
	}
	for (j = n - x; j < n; ++j) {
		if (zero[j] == 0) {//将没有出现0的列再进行操作
			for (i = n - x; i < n; ++i) {
				if (a[i][j] < MIN) {
					MIN = a[i][j];
				}
			}
			for (i = n - x; i < n; ++i) {
				a[i][j] -= MIN;
			}
			zero[j] = 1;//标记
			MIN = 100;//重置MIN!!
		}
	}
	sum += a[n + 1 - x][n + 1 - x];//删除第2行与第2列,并组成新矩阵
	a[n + 1 - x][n + 1 - x] = a[n - x][n - x];
	for (i = n + 2 - x; i < n; ++i) {
		a[n + 1 - x][i] = a[n - x][i];
		a[i][n + 1 - x] = a[i][n - x];
	}
	f(x - 1);//进行下一次递归
}
int main()
{
	cin >> n;
	int num = n;
	while (num--) {
		for (int i = 0; i < n; ++i) {
			for (int j = 0; j < n; ++j) {
				cin >> a[i][j];
			}
		}
		sum = 0;//重置sum
		f(n);
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值