题目:http://poj.org/problem?id=2078
暴搜加剪枝:rotate实际上是相对的,所以第一行可以不动,而且当发现一行的和不小于当前结果时,可以立马结束本次搜索,另外,取模运算真的很慢呀。。。
#include <cstdio>
#include <algorithm>
using namespace std;
#define INF 999999999
int n, matrix[7][7];
int offset[7], ans;
void check()
{
int maxsum = -INF;
for(int j = 0; j < n; ++j){
int sum = 0;
for(int i = 0; i < n; ++i){
int k = j + offset[i];
sum += matrix[i][k < n ? k : k - n];
}
if(sum >= ans) return;
maxsum = max(maxsum, sum);
}
ans = maxsum;
}
void dfs(int i)
{
if(i == n){
check();
return;
}
int& shift = offset[i];
for(shift = 0; shift < n; ++shift) dfs(i + 1);
}
int main()
{
while(scanf("%d", &n), n != -1){
for(int i = 0; i < n; ++i)
for(int j = 0; j < n; ++j)
scanf("%d", matrix[i] + j);
ans = INF;
dfs(1);
printf("%d\n", ans);
}
return 0;
}
如果手动模拟递归的话,又可以优化一些:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define INF 999999999
int n, matrix[7][7];
int offset[7], ans;
void check()
{
int maxsum = -INF;
for(int j = 0; j < n; ++j){
int sum = 0;
for(int i = 0; i < n; ++i){
int k = j + offset[i];
sum += matrix[i][k < n ? k : k - n];
}
if(sum >= ans) return;
maxsum = max(maxsum, sum);
}
ans = maxsum;
}
int main()
{
int i, j;
while(scanf("%d", &n), n != -1){
for(i = 0; i < n; ++i)
for(j = 0; j < n; ++j)
scanf("%d", matrix[i] + j);
if(n == 1){
printf("%d\n", matrix[0][0]);
continue;
}
ans = INF;
memset(offset, 0, n << 2);
while(!offset[0]){
for(i = 0; i < n; ++i){
offset[n-1] = i;
check();
}
for(j = n-2; j > -1 && ++offset[j] == n; --j) offset[j] = 0;
}
printf("%d\n", ans);
}
return 0;
}