孩子实在改不出来了 qwq
  • 板块UVA1309 Sudoku
  • 楼主Ivan422
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/11/27 22:26
  • 上次更新2024/11/28 07:07:34
查看原帖
孩子实在改不出来了 qwq
662425
Ivan422楼主2024/11/27 22:26
// ExFish UVA1309 Solution Version 1
#include<bits/stdc++.h>
using namespace std;
const int N=17;
string s;
int LOG[1<<16],mx_dfs,popc[1<<16];
char a[N][N];
int can_put_in[N][N]; // Can Put In A Number: BIN

inline void put_a_number_in(int x,int y,int z){ // Put Number
	for(int i=1;i<=16;i++){
		can_put_in[x][i]&=~(1<<z); // Row Can't Put In
		can_put_in[i][y]&=~(1<<z); // Col Can't Put In
	}
	// Case Can't Put In
	int case_x=(x-1)/4*4+1,case_y=(y-1)/4*4+1;
	for(int i=case_x;i<case_x+4;i++)for(int j=case_y;j<case_y+4;j++){
		can_put_in[i][j]&=~(1<<z);
	}
}
bool dfs(int last_block_cnt){ // Dfs
	cout<<last_block_cnt<<"\n";
	if(last_block_cnt==0){ // Find A Solution
		for(int i=1;i<=16;i++)printf("%s\n",a[i]+1);
		return 1;
	}
	int now_can_put_in[N][N];
	memcpy(now_can_put_in,can_put_in,sizeof(now_can_put_in));
	int the_best_cnt=16+1,the_best_x,the_best_y;
	// 1. Find Only & Now Search The Best
	for(int i=1;i<=16;i++){
		for(int j=1;j<=16;j++){
			if(a[i][j]!='-')continue; // There is a number
			if(can_put_in[i][j]==0)return 0; // No Answer
			if(popc[can_put_in[i][j]]==1){ // Only One
				a[i][j]=LOG[can_put_in[i][j]]+'A';
				put_a_number_in(i,j,LOG[can_put_in[i][j]]); // Put In
				if(dfs(last_block_cnt-1))return 1; // Dfs
				a[i][j]='-'; // Wrong, This Solution Need To Destroyed
				memcpy(can_put_in,now_can_put_in,sizeof(now_can_put_in));
				return 0; // Destroyed
			}
			if(popc[can_put_in[i][j]]<the_best_cnt){ // Search The Best
				the_best_cnt=popc[can_put_in[i][j]];
				the_best_x=i;
				the_best_y=j;
			}
		}
	}
	// 2. Find The Best Col
	for(int i=1;i<=16;i++){
		int this_col=0,need_to_solve=0;
		for(int j=1;j<=16;j++){
			if(a[i][j]=='-')need_to_solve++; // Find Need To Solve Place
			else this_col|=(1<<(a[i][j]-'A')); // Mark It
		}
		if(need_to_solve==0)continue; // Full
		for(int x=0;x<16;x++){ // Number
			if((this_col>>x)&1)continue; // Full
			int want_to_put=0,put_position=0;
			for(int j=1;j<=16;j++){
				if(a[i][j]!='-')continue; // There is a number
				if(((can_put_in[i][j]>>x)&1)==0)continue; // Can't Put It
				want_to_put++;
				put_position=j;
				if(want_to_put>1)break; // Can't Solve It
			}
			if(want_to_put==0)return 0; // All Kill
			if(want_to_put!=1)continue; // Can't Solve It
			a[i][put_position]=x+'A';
			put_a_number_in(i,put_position,x); // Put In
			if(dfs(last_block_cnt-1))return 1; // Dfs
			a[i][put_position]='-'; // Wrong, This Solution Need To Destroyed
			memcpy(can_put_in,now_can_put_in,sizeof(now_can_put_in));
			return 0; // Destroyed
		}
	}
	// 3. Find The Best Row
	for(int i=1;i<=16;i++){
		int this_row=0,need_to_solve=0;
		for(int j=1;j<=16;j++){
			if(a[j][i]=='-')need_to_solve++; // Find Need To Solve Place
			else this_row|=(1<<(a[j][i]-'A')); // Mark It
		}
		if(need_to_solve==0)continue; // Full
		for(int x=0;x<16;x++){ // Number
			if((this_row>>x)&1)continue; // Full
			int want_to_put=0,put_position=0;
			for(int j=1;j<=16;j++){
				if(a[j][i]=='-')continue; // There is a number
				if(((can_put_in[j][i]>>x)&1)==0)continue; // Can't Put It
				want_to_put++;
				put_position=j;
				if(want_to_put>1)break; // Can't Solve It
			}
			if(want_to_put==0)return 0; // All Kill
			if(want_to_put!=1)continue; // Can't Solve It
			a[put_position][i]=x+'A';
			put_a_number_in(put_position,i,x); // Put In
			if(dfs(last_block_cnt-1))return 1; // Dfs
			a[put_position][i]='-'; // Wrong, This Solution Need To Destroyed
			memcpy(can_put_in,now_can_put_in,sizeof(now_can_put_in));
			return 0; // Destroyed
		}
	}
	// 4. Find The Best Case
	for(int x=1;x<=13;x+=4)for(int y=1;y<=13;y+=4){
		int this_case=0,need_to_solve=0;
		for(int i=x;i<x+4;i++)for(int j=y;j<y+4;j++){
			if(a[i][j]=='-')need_to_solve++; // Find Need To Solve Place
			else this_case|=(1<<(a[i][j]-'A')); // Mark It			
		}
		if(need_to_solve==0)continue; // Full
		for(int k=0;k<16;k++){
			if((this_case>>k)&1)continue; // Full
			int want_to_put=0,put_position_x=0,put_position_y=0;			
			for(int i=x;i<x+4;i++)for(int j=y;j<y+4;j++){
				if(a[i][j]!='-')continue; // There is a number
				if(((can_put_in[i][j]>>k)&1)==0)continue; // Can't Put It
				want_to_put++;
				put_position_x=i,put_position_y=j;
			}			
			if(want_to_put==0)return 0; // All Kill
			if(want_to_put!=1)continue; // Can't Solve It
			a[put_position_x][put_position_y]=k+'A';
			put_a_number_in(put_position_x,put_position_y,k); // Put In
			if(dfs(last_block_cnt-1))return 1; // Dfs
			a[put_position_x][put_position_y]='-'; // Wrong, This Solution Need To Destroyed
			memcpy(can_put_in,now_can_put_in,sizeof(now_can_put_in));
			return 0; // Destroyed
		}		
	}
	// Last Search
	for(int i=can_put_in[the_best_x][the_best_y];i;i-=i&-i){
		int number=LOG[i&-i];
		a[the_best_x][the_best_y]=number+'A';
		put_a_number_in(the_best_x,the_best_y,number); // Put In
		if(dfs(last_block_cnt-1))return 1; // Dfs
		a[the_best_x][the_best_y]='-'; // Wrong, This Solution Need To Destroyed
		memcpy(can_put_in,now_can_put_in,sizeof(now_can_put_in));
	}
	return 0; // Destroyed
}
int _;
int main(){
	for(int i=0;i<16;i++)LOG[1<<i]=i;
	for(int i=0;i<(1<<16);i++)for(int j=i;j;j-=j&-j)popc[i]++;
	while(~scanf("%s",a[1]+1)){ // Input The Sudoku
		if(_)puts("");
		++_;
		for(int j=2;j<=16;j++)scanf("%s",a[j]+1);
		for(int i=1;i<=16;i++)for(int j=1;j<=16;j++)can_put_in[i][j]=(1<<16)-1;
		mx_dfs=0;
		for(int i=1;i<=16;i++)for(int j=1;j<=16;j++){
			if(a[i][j]=='-')mx_dfs++;
			else put_a_number_in(i,j,a[i][j]-'A');
		}
		dfs(mx_dfs);
	}
	return 0;
}
2024/11/27 22:26
加载中...