AcWing 166. 數獨

LeBronGod發表於2020-10-08

在這裡插入圖片描述

題意:

完成數獨

思路:

看到題目,這肯定是搜尋,但是試了一發普通的直接就超時了,肯定要加一些剪枝和優化,首先是位運算優化可以將每一行,每一列,每一個九宮格,都利用一個九位二進位制數儲存,當前還有哪些數字可以填寫,再一個我們肯定是從限制性最高的那個點開始填的,其實每次都是填限制最多的那個數,
涉及到一個lowbit函式:當前得需要用lowbit運算取出當前可以能填的數字.

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
char mp[10][10];//二維和一維存放 
int c[10],r[10],g[10];//行與列 
int cnt[1100],num[1100];
int k,tot;
int lowbit(int x) {
	return x&(-x);
}
int get(int x,int y) {
    return ((x/3)*3)+(y/3);
}
void fun(int x,int y,int z) {
	r[x]^=1<<z;
	c[y]^=1<<z;
	g[get(x,y)]^=1<<z;
}
int dfs(int now) {
	if(now == 0) return 1;
	int tmp = 10,x,y;
	for(int i=0;i<9;i++) {
		for(int j=0;j<9;j++) {
			if(mp[i][j]!='.') continue;
			int val = r[i] & c[j] & g[get(i,j)];
			if(!val) return 0;
			if(cnt[val]<tmp) {
				tmp = cnt[val];
				x = i,y = j;
			}
		}
	}
	int val = r[x] & c[y] & g[get(x,y)];
	for(;val;val-=lowbit(val)) {
		int z = num[lowbit(val)];
		mp[x][y] = z+'1';
		fun(x,y,z);
		if(dfs(now-1)) return 1;
		fun(x,y,z);
		mp[x][y] = '.';
	}
	return 0;
}
int main()
{
    for(int i=0;i<1<<9;i++) {//預處理初始能放的數有多少個
		for(int j=i;j;j-=lowbit(j)) {
			cnt[i]++;
		}
	} 
	for(int i=0;i<9;i++) num[1<<i] = i;
	char s[100];
	while(scanf("%s",s)&&s[0]!='e') {
		for(int i=0;i<9;i++) c[i] = r[i] = g[i] = (1<<9)-1;
		for(int i=0;i<9;i++) {
		    for(int j=0;j<9;j++) {
		        mp[i][j] = s[i*9+j];
		    }
		}
	    tot=0;
		for(int i=0;i<9;i++) {
			for(int j=0;j<9;j++) {
				if(mp[i][j]!='.') {
					fun(i,j,mp[i][j]-'1');
				} else {
					tot++;
				}	
			}
		}
		dfs(tot);
		for(int i=0;i<9;i++) {
			for(int j=0;j<9;j++) {
				s[i*9+j] = mp[i][j];
			}
		}
		puts(s);
	}
}

相關文章