「NOIP2009」靶形数独

传送门
Luogu

解题思路

这题其实挺简单的。
首先要熟悉数独,我们应该要优先搜索限制条件多的行,也就是可能方案少的行,显然这样可以剪枝,然后再发挥一下dfs的基本功就可以了。

细节注意事项

  • 爆搜题,你们都懂。。。

参考代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <ctime>
#define rg register
using namespace std;
template < typename T > inline void read(T& s) {
	s = 0; int f = 0; char c = getchar();
	while (!isdigit(c)) f |= c == '-', c = getchar();
	while (isdigit(c)) s = s * 10 + (c ^ 48), c = getchar();
	s = f ? -s : s;
}

const int s[10][10] = {
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 6, 6, 6, 6, 6, 6, 6, 6, 6 },
	{ 0, 6, 7, 7, 7, 7, 7, 7, 7, 6 },
	{ 0, 6, 7, 8, 8, 8, 8, 8, 7, 6 },
	{ 0, 6, 7, 8, 9, 9, 9, 8, 7, 6 },
	{ 0, 6, 7, 8, 9,10, 9, 8, 7, 6 },
	{ 0, 6, 7, 8, 9, 9, 9, 8, 7, 6 },
	{ 0, 6, 7, 8, 8, 8, 8, 8, 7, 6 },
	{ 0, 6, 7, 7, 7, 7, 7, 7, 7, 6 },
	{ 0, 6, 6, 6, 6, 6, 6, 6, 6, 6 }
};

const int p[10][10] = {
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 1, 1, 1, 2, 2, 2, 3, 3, 3 },
	{ 0, 1, 1, 1, 2, 2, 2, 3, 3, 3 },
	{ 0, 1, 1, 1, 2, 2, 2, 3, 3, 3 },
	{ 0, 4, 4, 4, 5, 5, 5, 6, 6, 6 },
	{ 0, 4, 4, 4, 5, 5, 5, 6, 6, 6 },
	{ 0, 4, 4, 4, 5, 5, 5, 6, 6, 6 },
	{ 0, 7, 7, 7, 8, 8, 8, 9, 9, 9 },
	{ 0, 7, 7, 7, 8, 8, 8, 9, 9, 9 },
	{ 0, 7, 7, 7, 8, 8, 8, 9, 9, 9 },	
};

struct node { int id, cnt; }a[10];
inline bool cmp(const node& x, const node& y) { return x.cnt > y.cnt; }
int ans = -1, mp[10][10]; bool Line[10][10], Clmn[10][10], Palc[10][10];

inline void dfs(int i, int j, int line, int sum) {
	if (line > 9) { ans = max(ans, sum); return; }
	if (j == 10) { dfs(a[line + 1].id, 1, line + 1, sum); return ; }
	if (mp[i][j]) { dfs(i, j + 1, line, sum); return; }
	for (rg int x = 1; x <= 9; ++x) {
		if (Line[i][x]) continue;
		if (Clmn[j][x]) continue;
		if (Palc[p[i][j]][x]) continue;
		Line[i][x] = Clmn[j][x] = Palc[p[i][j]][x] = 1, mp[i][j] = x;
		dfs(i, j + 1, line, sum + x * s[i][j]);
		Line[i][x] = Clmn[j][x] = Palc[p[i][j]][x] = 0, mp[i][j] = 0;
	}
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.in", "r", stdin);
#endif
	for (rg int i = 1; i <= 9; ++i) a[i].id = i;
	int tmp = 0;
	for (rg int i = 1; i <= 9; ++i)
		for (rg int j = 1; j <= 9; ++j) {
			int x; read(x), mp[i][j] = x;
			if (x) Line[i][x] = 1, Clmn[j][x] = 1, Palc[p[i][j]][x] = 1, ++a[i].cnt, tmp += x * s[i][j];
		}
	sort(a + 1, a + 10, cmp);
	dfs(a[1].id, 1, 0, tmp);
	printf("%d\n", ans);
	return 0;
}

完结撒花 \(qwq\)

posted @ 2019-10-28 17:14  Sangber  阅读(164)  评论(3编辑  收藏  举报