题目链接:
题目大意:
古老的皇后问题。。换了个要求
要求棋盘中皇后格子中对应值之和的最大值。
格子中数值排列规律是从左往右严格递增,从上往下严格递增。
思路:
回溯 + 剪枝
另外这题还学到一中新的姿势,处理正方形网格中对角线上值的问题 - 》
对于第i行,第j列的元素,它的所有右上和左下对角线上的i+j都相等,它的所有左上和右下对角线上的j+n-i都相等。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL long long
#define N 100
int n;
int a[N][N];
int sum[N];
LL ans;
int num;
bool col[N],lu[N],ru[N];
void dfs(int t,LL s){
if(t==0){
if(s>ans) ans=s;
return;
}
if(++num > 10000000) return; //层数剪枝:神技!
if(s + sum[t] <= ans) return; // 极值剪枝:常用!
for(int i=n;i>=1;i--){
if(col[i] || lu[i+t] || ru[t+n-i]) continue;
col[i] = lu[i+t] = ru[t+n-i] = true;
dfs(t-1,s+a[t][i]);
col[i] = lu[i+t] = ru[t+n-i] = false;
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
sum[0] = 0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&a[i][j]);
}
sum[i] = sum[i-1]+a[i][n];
}
memset(col,false,sizeof(col));
memset(lu,false,sizeof(lu));
memset(ru,false,sizeof(ru));
ans = 0,num=0;
dfs(n,0);
printf("%lld\n",ans);
}
return 0;
}