[luoguP1074] 靶形数独(搜索)

传送门

 

75分,太菜,不会优化了,吐了。

几点优化。

1.先搜索容易确定的位置

2.从中心往周围搜

3.枚举数字的时候倒序枚举

4.如果没有枚举到的数字都是最优情况的话也不能比当前ans大就剪枝

5.位运算

 

#include <cstdio>
#include <iostream>
#include <algorithm>
#define max(x, y) ((x) > (y) ? (x) : (y))
#define tu(i, j) (((i) - 1) / 3 * 3 + ((j) - 1) / 3 + 1)

int ans = -1, cnt;
int hang[10], lie[10], jiu[10], shu[10], a[10][10], num[10][10], point[11];

struct node
{
	int pt, x, y, z;
	node(int pt = 0, int x = 0, int y = 0, int z = 0) : pt(pt), x(x), y(y), z(z) {}
}p[101];

inline int read()
{
	int x = 0, f = 1;
	char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
	for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
	return x * f;
}

inline bool cmp(node x, node y)
{
	return x.z > y.z || (x.z == y.z && x.pt > y.pt);
}

inline int pd(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;
}

inline bool check(int sum)
{
	int i, j, k, top;
	k = 10;
	top = point[k];
	for(i = 9; i >= 1; i--)
		for(j = 1; j <= 9 - shu[i]; j++)
			if(top) top--, sum += i * k;
			else
			{
				while(!top && k > 6) k--, top = point[k];
				top--;
				sum += i * k;
			}
	return sum > ans;
}

inline void dfs(int x, int y, int k, int sum)
{
	if(k > cnt)
	{
		ans = max(ans, sum);
		return;
	}
	for(int i = 9; i >= 1; i--)
		if(!(hang[x] & (1 << i - 1)) && !(lie[y] & (1 << i - 1)) && !(jiu[tu(x, y)] & (1 << i - 1)))
		{
			shu[i]++;
			point[pd(x, y)]--; 
			lie[y] |= 1 << i - 1;
			hang[x] |= 1 << i - 1;
			jiu[tu(x, y)] |= 1 << i - 1;
			if(check(sum + p[k].pt * i)) dfs(p[k + 1].x, p[k + 1].y, k + 1, sum + p[k].pt * i);
			jiu[tu(x, y)] ^= 1 << i - 1;
			hang[x] ^= 1 << i - 1;
			lie[y] ^= 1 << i - 1;
			point[pd(x, y)]++;
			shu[i]--;
		}
}

int main()
{
	int i, j, k, l, x, sum = 0;
	point[6] = 32;
	point[7] = 24;
	point[8] = 16;
	point[9] = 8;
	point[10] = 1;
	for(i = 1; i <= 9; i++)
		for(j = 1; j <= 9; j++)
		{
			shu[a[i][j] = read()]++;
			sum += a[i][j] * pd(i, j);
			if(a[i][j])
			{
				point[pd(i, j)]--;
				lie[j] |= 1 << a[i][j] - 1;
				hang[i] |= 1 << a[i][j] - 1;
				jiu[tu(i, j)] |= 1 << a[i][j] - 1;
			}
		}
	for(i = 1; i <= 9; i++)
		for(j = 1; j <= 9; j++)
		{
			for(k = 1; k <= 9; k++)
				if(a[i][k] && k != j)
					num[i][j]++;
			for(k = 1; k <= 9; k++)
				if(a[k][j] && k != i)
					num[i][j]++;
			for(k = 1; k <= 9; k++)
				for(l = 1; l <= 9; l++)
					if(tu(i, j) == tu(k, l) && a[k][l] && !(i == k && j == l))
						num[i][j]++;
		}
	for(i = 1; i <= 9; i++)
		for(j = 1; j <= 9; j++)
			if(!a[i][j])
				p[++cnt] = node(pd(i, j), i, j, num[i][j]);
	std::sort(p + 1, p + cnt + 1, cmp);
	dfs(p[1].x, p[1].y, 1, sum);
	printf("%d\n", ans);
	return 0;		
}

  

posted @ 2017-08-02 16:48  zht467  阅读(131)  评论(0)    收藏  举报