[DFS]P1074 [NOIP 2009 提高组] 靶形数独 题解
搜索练习题,细节我认为不是很多。
由于暴搜是 \(O(n^n)\) 一个小trick是从0少的层级开始搜索。加上本来有很多填上的数与每一行列块不能填同样数的限制,复杂度完全跑不满。
感觉没啥好讲的,写就完了。有问题看代码吧,都很明了。
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
inline int belong(int x, int y) {
return (x - 1) / 3 * 3 + (y - 1) / 3 + 1;
}
inline int mark(int x, int y) {
if(x == 1 || y == 1 || x == 9 || y == 9) return 6;
if(x == 2 || y == 2 || x == 8 || y == 8) return 7;
if(x == 3 || y == 3 || x == 7 || y == 7) return 8;
if(x == 4 || y == 4 || x == 6 || y == 6) return 9;
return 10;
}
pair<int, int> cnt[10], List[100];
bool lie[10][10], hang[10][10], form[10][10];
int a[10][10], tot, ans = -1, sum;
void dfs(int now, int sum) {
if(now == tot + 1) {//由于会多加1个,所以要判断一下
ans = max(ans, sum);
return;
}
rep(i, 1, 9) {
int X = List[now].first, Y = List[now].second;//这里注意不要开成全局变量了!
if(!lie[Y][i] || !hang[X][i] || !form[belong(X, Y)][i]) {
continue;
}
hang[X][i] = false;
lie[Y][i] = false;
form[belong(X, Y)][i] = false;
dfs(now + 1, sum + i * mark(X, Y));
hang[X][i] = true;
lie[Y][i] = true;
form[belong(X, Y)][i] = true;
}
}
int main() {
memset(lie, true, sizeof lie);
memset(hang, true, sizeof hang);
memset(form, true, sizeof form);
rep(i, 1, 9) {
cnt[i].second = i;
rep(j, 1, 9) {
cin >> a[i][j];
cnt[i].first += !a[i][j];
sum += a[i][j] * mark(i, j);
lie[j][a[i][j]] = false;
hang[i][a[i][j]] = false;
form[belong(i, j)][a[i][j]] = false;
}
}
sort(cnt + 1, cnt + 10);
rep(i, 1, 9) {
rep(j, 1, 9) {
if(!a[cnt[i].second][j]) {
List[++tot].first = cnt[i].second, List[tot].second = j;
//把待搜索的点全部放进去,便于搜索
}
}
}
dfs(1, sum);
cout << ans;
return 0;
}

浙公网安备 33010602011771号