位运算

Roger 2020-07-28 16:02:19 2020-07-28 16:03:00

#include<iostream>
#include<cstdio>
using namespace std;

inline int read()
{
	int x = 0,f = 1;
	char ch = getchar();
	while(ch>'9'||ch<'0'){
		if(ch=='-') f = -1;
		ch = getchar();
	}
	while(ch<='9'&&ch>='0'){
		x = x * 10 + ch-'0';
		ch = getchar();
	}
	return x*f;
}
int f[1<<9],cnt[1<<9],ans=-1,num,a[9],b[9],c[9];
int map[9][9],biao[9][9]={{6,6,6,6,6,6,6,6,6},
						  {6,7,7,7,7,7,7,7,6},
						  {6,7,8,8,8,8,8,7,6},
						  {6,7,8,9,9,9,8,7,6},
						  {6,7,8,9,10,9,8,7,6},
						  {6,7,8,9,9,9,8,7,6},
						  {6,7,8,8,8,8,8,7,6},
						  {6,7,7,7,7,7,7,7,6},
						  {6,6,6,6,6,6,6,6,6}};
void work(int i, int j, int k)
{
	a[i] ^= (1<<k);
	b[j] ^= (1<<k);
	c[i/3*3+j/3] ^= (1<<k);
}
void dfs(int num)
{
	if(!num)
	{
		int out=0;
		for(int i=0;i<9;i++)	
			for(int j=0;j<9;j++)
				out+=map[i][j]*biao[i][j];
		ans=max(ans,out);
		return ;
	}
	int find=10,x,y,k;
	for(int i = 0; i < 9; i++)
		for(int j = 0; j < 9;j++)
			if(!map[i][j])
			{
				k=a[i]&b[j]&c[i/3*3+j/3];
				if(cnt[k]<find)
				{
					x=i,y=j;
					find=cnt[k];
				}
				if(find==0) return;
			}
	k=a[x]&b[y]&c[x/3*3+y/3];
	while(k)
	{
		int now=f[k&(-k)];
		map[x][y]=now+1;
		work(x,y,now);
		dfs(num-1);
		work(x,y,now);
		map[x][y]=0;
		k=k-(k&(-k));
	}
}
int main()
{
	for(int i = 0; i < (1<<9); i++)
		cnt[i] = cnt[i-(i&(-i))]+1;
	cnt[0] = 0; 
	for(int i = 0; i < 9; i++)
		f[1<<i] = i, a[i] = b[i] = c[i] = 511;
	for(int i = 0; i < 9; i++)
		for(int j = 0; j < 9; j++)
		{
			map[i][j] = read();
			if(map[i][j]) work(i,j,map[i][j]-1);
			else num++;
		}
	dfs(num);
	printf("%d",ans);
	return 0;
}