[LuoguP1074]靶形数独_搜索

靶形数独

题目链接https://www.luogu.org/problem/P1074

数据范围:略。


题解

传说中的大爆搜题啊。

我觉得这种题就是你能想到什么优化就直接上什么优化....

这个题我们就贪心的选行,就是按照每行$0$的个数从小到大排序依次填。

然后我们填的时候需要记录:当前要填的数,在行、列、九宫格里是否出现过即可。

还有,分数是$5\sim 10$,不是$1$到$5$.....

代码

#include <bits/stdc++.h>

#define N 110 

using namespace std;

char *p1, *p2, buf[100000];

#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )

int rd() {
	int x = 0, f = 1;
	char c = nc();
	while (c < 48) {
		if (c == '-')
			f = -1;
		c = nc();
	}
	while (c > 47) {
		x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
	}
	return x * f;
}

struct Node {
	int x, y;
};

inline bool cmp(const Node &a, const Node &b) {
	return a.y < b.y;
}

const int n = 9;

inline int id(Node a) {
	return n * (a.x - 1) + a.y;
}

inline int id(int x, int y) {
	return n * (x - 1) + y;
}

inline Node rz(int x) {
	return (Node) {(x - 1) / n + 1, (x - 1) % n + 1};
}

inline int bid(int al) {
	int x = rz(al).x, y = rz(al).y;
	x = (x - 1) / 3 + 1, y = (y - 1) / 3 + 1;
	return (x - 1) * 3 + y;
}

int Map[N], q[N], Score[N], ans = 0, fil[N];

bool vis[3][10][10];

Node b[11];

void dfs(int k) {
	if (k == 82) {
		// puts("??");
		int sum = 0;
		for (int i = 1; i <= n; i ++ ) {
			for (int j = 1; j <= n; j ++ ) {
				sum += fil[id(i, j)] * Score[id(i, j)];
			}
		}

		// for (int i = 1; i <= n; i ++ ) {
		// 	for (int j = 1; j <= n; j ++ ) {
		// 		printf("%d ", fil[id(i, j)]);
		// 	}
		// 	puts("");
		// }
		// puts("");
		ans = max(ans, sum);
		return;
	}

	int x = rz(q[k]).x, y = rz(q[k]).y;
	// printf("%d %d\n", x, y);
	if (!Map[id(x, y)]) {
		for (int i = 1; i <= 9; i ++ ) {
			// x, y, i
			if (!vis[0][x][i] && !vis[1][y][i] && !vis[2][bid(id(x, y))][i]) {
				vis[0][x][i] = vis[1][y][i] = vis[2][bid(id(x, y))][i] = true;
				fil[id(x, y)] = i;
				dfs(k + 1);
				vis[0][x][i] = vis[1][y][i] = vis[2][bid(id(x, y))][i] = false;
				fil[id(x, y)] = 0;
			}
		}
	}
	else {
		dfs(k + 1);
	}
}

int main() {
	for (int i = 1; i <= 9; i ++ ) {
		for (int j = 1; j <= 9; j ++ ) {
			Map[id(i, j)] = rd();
		}
	}

	for (int i = 1; i <= 9; i ++ ) {
		b[i].x = i;
		for (int j = 1; j <= 9; j ++ ) {
			int v = Map[id(i, j)];
			if (!v)
				b[i].y ++ ;
			else {
				vis[0][i][v] = vis[1][j][v] = vis[2][bid(id(i, j))][v] = true;
				fil[id(i, j)] = v;
			}
		}
	}

	sort(b + 1, b + n + 1, cmp);
	for (int i = 1; i <= n; i ++ ) {
		for (int j = 1; j <= n; j ++ ) {
			int x = b[i].x, y = j;
			q[id(i, j)] = id(x, y);
		}
	}

	// init_score
	for (int i = 1; i <= n; i ++ ) {
		for (int j = 1; j <= n; j ++ ) {
			Score[id(i, j)] = 5;
		}
	}

	for (int i = 1; i <= 5; i ++ ) {
		int x = i, y = n - i + 1;
		for (int l = x; l <= y; l ++ ) {
			for (int r = x; r <= y; r ++ ) {
				Score[id(l, r)] ++ ;
			}
		}
	}

	// for (int i = 1; i <= n; i ++ ) {
	// 	for (int j = 1; j <= n; j ++ ) {
	// 		printf("%d ", Score[id(i, j)]);
	// 	}
	// 	puts("");
	// }

	dfs(1);

	if (!ans) {
		puts("-1");
	}
	else {
		cout << ans << endl ;
	}
	return 0;
}
posted @ 2019-10-24 16:24  JZYshuraK_彧  阅读(138)  评论(0编辑  收藏  举报