题目描述
现在有一个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;
}