洛谷 P1074 靶形数独(dfs)

题目传送

1.用dt[]存待填的位置,保存行列宫每个数字的状态。
2.为防止TLE,我们可以从0最少的行开始搜。

#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 12;

struct node {
	int id, num;
	bool operator < (const node& a) {
		return num < a.num;
	}
}cnt_0[maxn]; //每行0的数量

int cnt, ans, maxx;
int map[maxn][maxn], dt[maxn * maxn][3];
// 存初始            待填的位置
bool hang[maxn][maxn], lie[maxn][maxn], gong[maxn][maxn];
// 标记是否用过

//返回宫
int get_gong(int x, int y)
{
	return (x - 1) / 3 * 3 + (y - 1) / 3 + 1;
}

//分数
int score(int x, int y)
{
	if (x == 1 || x == 9 || y == 1 || y == 9) return 6;
	if (x == 2 || x == 8 || y == 2 || y == 8) return 7;
	if (x == 3 || x == 7 || y == 3 || y == 7) return 8;
	if (x == 4 || x == 6 || y == 4 || y == 6) return 9;
	return 10;
}

void dfs(int u, int tot)
{
	//填完更新答案返回
	if (u == cnt) {
		maxx = max(maxx, tot);
		return;
	}
	for (int i = 1; i <= 9; i++) {
		//判断i是否可填
		if (!hang[dt[u][0]][i] && !lie[dt[u][1]][i] && !gong[dt[u][2]][i]) {
			hang[dt[u][0]][i] = 1;
			lie[dt[u][1]][i] = 1;
			gong[dt[u][2]][i] = 1;
			dfs(u + 1, tot + i * score(dt[u][0], dt[u][1]));
			hang[dt[u][0]][i] = 0;
			lie[dt[u][1]][i] = 0;
			gong[dt[u][2]][i] = 0;
		}
	}
}

int main(void)
{
	for (int i = 1; i <= 9; i++) {
		for (int j = 1; j <= 9; j++) {
			cin >> map[i][j];
			if (!map[i][j]) {
				cnt_0[i].id = i;
				cnt_0[i].num++; //i行0的数量
			}
			else {
				hang[i][map[i][j]] = 1;
				lie[j][map[i][j]] = 1;
				gong[get_gong(i, j)][map[i][j]] = 1;
				ans += map[i][j] * score(i, j);
			}
		}
	}
	sort(cnt_0 + 1, cnt_0 + 10); //按0的数量排序
	for (int i = 1; i <= 9; i++) {
		for (int j = 1; j <= 9; j++) {
			//保存待填的位置
			if (!map[cnt_0[i].id][j]) {
				dt[cnt][0] = cnt_0[i].id;
				dt[cnt][1] = j;
				dt[cnt++][2] = get_gong(cnt_0[i].id, j);
			}
		}
	}
	dfs(0, 0);
	if (!maxx) cout << "-1" << endl; //无解
	else cout << ans + maxx << endl;
	return 0;
}
发布了30 篇原创文章 · 获赞 50 · 访问量 5280

猜你喜欢

转载自blog.csdn.net/qq_43054573/article/details/104674456