(POJ2078)Matrix-DFS

                                                  Matrix

Time Limit: 2000MS Memory Limit: 30000K
Total Submissions: 4254 Accepted: 2242

Description

Given an n*n matrix A, whose entries Ai,j are integer numbers ( 0 <= i < n, 0 <= j < n ). An operation SHIFT at row i ( 0 <= i < n ) will move the integers in the row one position right, and the rightmost integer will wrap around to the leftmost column.


You can do the SHIFT operation at arbitrary row, and as many times as you like. Your task is to minimize

max0<=j< n{Cj|Cj=Σ0<=i< nAi,j}

Input

The input consists of several test cases. The first line of each test case contains an integer n. Each of the following n lines contains n integers, indicating the matrix A. The input is terminated by a single line with an integer −1. You may assume that 1 <= n <= 7 and |Ai,j| < 104.

Output

For each test case, print a line containing the minimum value of the maximum of column sums.

Sample Input

2
4 6
3 7
3
1 2 3
4 5 6
7 8 9
-1

Sample Output 

11
15

题目分析:

题目大意是每层可以向右循环旋转(例:123 312 231)算出每种情况下矩阵每列的和,找出每列和的最大值,最小化最大值(例:假设当前有三列,每列的和为2 5 3,最大值为5,另一种情况下每列和为 3 4 6,最大值为6,最小的最大值为5)。

问题求解:

个人认为,这题类似于N皇后问题,N皇后问题的求解步骤是枚举每一层可能的情况,然后看在当前情况下是否可行,不可行则继续下种情况,直到找到当前层的可行情况而转入下一层。该问题也是分层枚举,枚举每层的情况,当到达矩阵最后一层后(其实是最后一层下一层)判断求出每列最大值,并最小化该值。

代码:

#include<iostream>
#include<algorithm>
using namespace std;

int n;
int A[8][16];
int sum[16];
int minimum=1000000; int maximum;

void DFS(int r) {
	if (r == n ) {                    //r表示当前为第几层,是从0到n-1的
		minimum = min(maximum, minimum);		//最小化最大值
		return;
	}
	
	for (int i = 0; i < n; i++) {				//i表示该层的第一个数字
		for (int j = 0; j < n; j++) {			//j表示相对与i的偏移量
			sum[j] = sum[j] + A[r][i + j];
		}
		//剪枝
		maximum = sum[0];
		for (int i = 1; i < n; i++) {			//求每列的最大值
			maximum = max(maximum, sum[i]);
		}

		if(maximum<=minimum)	//如果到达当前层后该情况下求出的最大值已经比最小化的最大值大,就不用在继续搜下去了。
		DFS(r + 1);
		for (int j = 0; j < n; j++) {
			sum[j] = sum[j] - A[r][i + j];
		}
	}
}

int main() {
	while (cin >> n&&n!=-1) {
		minimum = 1000000;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				cin >> A[i][j];
				A[i][j + n] = A[i][j];			//进行旋转操作时方便计算
			}
		}
		memset(sum, 0, sizeof(sum));
		DFS(0);
		cout << minimum << endl;
	}
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值