题目
解析
这题考的是搜索剪枝
可行性剪枝:
即判断当前行(列)是否已经超过L和剩下的格子都填最大值是否小于L,若是则剪枝。
当前行数大于1时,判断上一个填完的行是否等于L,若否,则剪枝。
当前行为最后一行,且当前列大于1时,判断上一个填完的列是否等于L,若否,则剪枝。
当前列大于1时,判断上一个列填的数是否大于L,若是则剪枝。
优化顺序剪枝:
从大到小枚举当前填的数
当前格子能填的最大数为min(L-当前行已经填的数,L-当前列已经填的数)
代码
#include <bits/stdc++.h>
using i64 = long long;
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int L, n;
cin >> L >> n;
vector<int> row(n), col(n);
int down = 0, up = L;
function<i64(int, int)> dfs = [&] (int x, int y) -> i64 {
if (x == n) {
return int(row[n - 1] == L && col[n - 1] == L);
}
if (row[x] > L || row[x] + (n - y) * up < L || col[y] > L || col[y] + (n - x) * up < L) return 0;
if (x > 0 && row[x - 1] != L) return 0;
if (x == n - 1 && y > 0 && col[y - 1] != L) return 0;
if (y > 0 && col[y - 1] > L) return 0;
i64 r = 0;
for (int i = min(L - col[y], L - row[x]); i >= 0; i--) {
row[x] += i;
col[y] += i;
r += dfs(x + ((y + 1) / n), (y + 1) % n);
row[x] -= i;
col[y] -= i;
}
return r;
};
cout << dfs(0, 0) << '\n';
return 0;
}