數獨----------------------------思維(dfs+優化策略)

在這裏插入圖片描述
在這裏插入圖片描述

#include<bits/stdc++.h>
using namespace std;
const int N=9;
char str[N*N+10];
int col[N],row[N],cel[3][3];//col,row存放每列每行應對的二進制位 。 cel[3][3]存放的是每一個3*3的矩陣狀態。
//需要哪一塊只需要cel[x/3][y/3]就行了 
int ones[1<<N],mp[1<<N];//統計有多少個1.每個1對應到哪一位 
inline int lowbit(int x)
{
	return x&(-x);
}
void init()
{
	for(int i=0;i<N;i++) row[i]=col[i]=(1<<N)-1;
	for(int i=0;i<3;i++)
		for(int j=0;j<3;j++) cel[i][j]=(1<<N)-1;
}
inline int get(int x,int y) //取行和列還有3*3的正方形中哪些數可取的,所以用& 
{
	return row[x]&col[y]&cel[x/3][y/3];
}
bool dfs(int cnt) //如果方案可行返回1,不可行返回-1 
{
	if(!cnt) return true;
	//找出可選方案最少的空格  (剪枝策略)
	int miv=10;
	int x,y;
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
		{
			if(str[i*9+j]=='.')
			{
				int t=ones[get(i,j)];
				if(t<miv)
				{
					miv=t;
					x=i;y=j;
				}
			}
		 } 
	for(int i=get(x,y);i;i-=lowbit(i))//取出這些1,是我們需要改變的 
	{
		int t=mp[lowbit(i)];//確定這個1在那個位置上 
		//修改狀態 
		row[x]-=(1<<t);
		col[y]-=(1<<t);
		cel[x/3][y/3]-=(1<<t);
		str[x*9+y]=t+'1';
		
		if(dfs(cnt-1)) return true;
		//恢復現場 
		row[x]+=(1<<t);
		col[y]+=(1<<t);
		cel[x/3][y/3]+=(1<<t);
		str[x*9+y]='.';
		
	}
	return false;
}
int main()
{
	for(int i=0;i<N;i++)  mp[1<<i]=i;//統計每個二進制位上1在哪個位置上 
	for(int i=0;i<(1<<N);i++) //ones記錄每個狀態有多少個1 
	{
		int s=0;
		for(int j=i;j;j-=lowbit(j)) s++;
		ones[i]=s;
	}
	while(cin>>str,str[0]!='e')
	{
		init();//初始化 
		
		//消除現有的數
		int cnt=0;
		for(int i=0,k=0;i<N;i++)
			for(int j=0;j<N;j++,k++) 
			{
				if(str[k]!='.')
				{
					int t=str[k]-'1';
					row[i]-=(1<<t);
					col[j]-=(1<<t);
					cel[i/3][j/3]-=(1<<t);
				}
				else cnt++;
			}
		dfs(cnt);
		cout<<str<<endl;
		
	 } 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章