一、题意

有若干组数据。
每组数据给一个8*8棋盘,棋盘上每个位置上有一个数字,要求你找出一个八皇后摆法,使得八皇后位置上的数字之和最大。输出这个最大值。

二、解析

经典的八皇后问题,做了一些小修改。但其实还是八皇后问题。
枚举出所有摆法然后维护出最大值即可。

三、代码

#include <iostream>
#include <cstring>
#include <iomanip>
using namespace std;
const int n = 8;
int k, a[n + 5][n + 5], ans, vis[3][n * 2 + 5];

void solve(int cur, int sum) {
    if(cur == n) {
        ans = max(ans, sum);
        return;
    }
    for(int i = 0; i < n; i ++) if(!vis[0][i] && !vis[1][cur + i] && !vis[2][cur - i + n]) {
        vis[0][i] = vis[1][cur + i] = vis[2][cur - i + n] = 1;
        solve(cur + 1, sum + a[cur][i]);
        vis[0][i] = vis[1][cur + i] = vis[2][cur - i + n] = 0;
    }
}

int main() {
    cin >> k;
    while(k --) {
        ans = 0;
        memset(vis, 0, sizeof(vis));
        for(int i = 0; i < n; i ++) for(int j = 0; j < n; j ++) cin >> a[i][j];
        solve(0, 0);
        cout << setw(5) << ans << endl;
    }
}

四、归纳

  • 八皇后问题:按行递归,然后在每行中枚举列,通过vis维护棋盘上每列和每个斜是否已经被占用(行就不用了,因为是按行递归的)。注意递归结束后要回溯,这样才能继续找下一个解。
  • 实际上八皇后问题还教了一种思考方式,就是:我想要确认某个条件时,自己去确认是比较费时的(遍历自己的行、列、斜是否冲突),但是找别人专门管这件事,然后直接去问他是最快的(vis数组专门维护占用情况)。工程上的模块化思想有点像这个,虽然没啥关系就是了...
  • 注意题目有输出格式,这个时候就要靠 iomanip 这个库了,setw(5)表示占位长度,还可以setfill('')表示用''占空位,还有fixed<<setprecision(n)表示保留n位小数等。这些是比较常用的。