递归问题之——平衡矩阵

 题目描述

现在有一个n阶正整数方阵(n<=7),现在可以对矩阵的任意一行进行左移,具体操作为:每次对于某一行a_i1,a_i2,…,a_in进行一次左移,最左边的元素移动到这一行的末尾,其他元素均向左移动一位,即变为a_i2,a_i3,…,a_in,a_i1。对某一行可以执行任意次的左移。
现在我们的目标是:通过对矩阵的每一行进行若干次左移,使得矩阵中每列和的最大值最小。

关于输入

输入包含多组数据。

目录

题目描述

关于输入

关于输出

例子输入

例子输出


对于每组数据,第一行为一个正整数n(1<=n<=7),代表矩阵的阶。接下来的n行,每行n个正整数(不超过10000),代表这个矩阵。
输入数据以一个-1为结尾代表输入结束。

关于输出

对于每组数据,输出一行一个正整数,为最小的最大列和。

例子输入
2
4 6
3 7
3
1 2 3
4 5 6
7 8 9
-1
例子输出
11
15

分析

这题的思路其实不难,就是令第一行不动,然后不断地把后面的某一行左移,然后求各列和的最大值,最后在好多个最大值中选出最小的那个就好了。具体地说,对于第二行,有如下几种情况:不左移、左移1次、左移2次······左移n-1次,然后分别对于这几种情况来穷举第三行的移动情况······以此类推,就可以穷举出所有的移动情况了。

代码不难给出:

#include<iostream>
using namespace std;
int n;
int a[7][7];
int i, j, k;
int max1;
void move_left(int a[7]) {//定义一个函数用来进行左移操作
	int temp;
	int i;
	temp = a[0];
	for (i = 0; i < n - 1; i++) {
		a[i] = a[i + 1];
	}
	a[n - 1] = temp;
}
int maxofmatrix(int a[7][7]) {//定义一个函数来求操作后的矩阵中各列和的最大值
	int max2 = 0;
	int sum;
	int i, j, k;
	for (i = 0; i < n; i++) {
		max2 += a[i][0];
	}
	for (j = 1; j < n; j++) {
		sum = 0;
		for (i = 0; i < n; i++) {
			sum += a[i][j];
		}
		if (sum > max2) {
			max2 = sum;
		}
	}
	return max2;
}
void minofmax(int a[7][7], int i) {//定义一个函数来求最大值中的最小值,其中,i表示接下来要对第i行进行操作
	if (i < n) {//只有当i<n时才能进行操作
		int j;
		int m;
		minofmax(a, i + 1);//如果第i行不进行左移,那么就直接跳到第i+1行
		for (j = 1; j < n; j++) {//j表示左移次数
			move_left(a[i]);
			m = maxofmatrix(a);//每次左移后都要算一下各列和的最大值
			if (m < max1) {
				max1 = m;
			}
			minofmax(a, i + 1);//第i行操作结束,对第i+1行重复上述操作
		}
	}
}
int main() {
	while (cin >> n) {
		if (n == -1) {
			break;
		}
		else {
			for (i = 0; i < n; i++) {
				for (j = 0; j < n; j++) {
					cin >> a[i][j];
				}
			}
		}
		max1 = maxofmatrix(a);
		minofmax(a, 1);
		cout << max1 << endl;
	}
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值