描述 | |
给定一个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;
}