(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;
}

猜你喜欢

转载自blog.csdn.net/xiaosi1524/article/details/81213489
今日推荐