poj 2676
思路:正常的数独题,用三个数组记录一下行列方格的状态,随便搜
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char s[12][12];
int mp[10][10];
bool r[10][10],c[10][10],g[10][10],flag;
bool check(int k,int x,int y)
{
if(r[x][k]==1)return false;
if(c[y][k]==1)return false;
int f=3*((x-1)/3)+(y-1)/3+1;
if(g[f][k]==1)return false;
return true;
}
void dfs(int x,int y)
{
if(flag||x==10)
{
flag=1;
return;
}
while(mp[x][y])
{
if(y==9)x++,y=1;
else y++;
if(x==10)
{
flag=1;
return;
}
}
int k=3*((x-1)/3)+(y-1)/3+1;
for(int i=1;i<=9;++i)
{
if(check(i,x,y))
{
mp[x][y]=i;
r[x][i]=1;
c[y][i]=1;
g[k][i]=1;
if(y==9)dfs(x+1,1);
else dfs(x,y+1);
if(flag)return;
mp[x][y]=0;
r[x][i]=0;
c[y][i]=0;
g[k][i]=0;
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(r,0,sizeof(r));
memset(c,0,sizeof(c));
memset(g,0,sizeof(g));
for(int i=1;i<=9;++i)
for(int j=1;j<=9;++j)
{
cin>>s[i][j];
mp[i][j]=s[i][j]-'0';
if(mp[i][j])
{
int k=3*((i-1)/3)+(j-1)/3+1;
r[i][mp[i][j]]=1;
c[j][mp[i][j]]=1;
g[k][mp[i][j]]=1;
}
}
flag=0;
dfs(1,1);
for(int i=1;i<=9;++i)
{
for(int j=1;j<=9;++j)
printf("%d",mp[i][j]);
puts("");
}
}
return 0;
}
poj 3074
思路:同样也是填数独,但这题数据很变态,我不会dc,所以只能二进制常数优化加上 每次填可选项最少的地方,这个可以用二进制下lowbit(x)运算实现,加了inline 735ms卡过
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char str[10][10];
int row[9], col[9], grid[9], cnt[512], num[512], tot;
inline int g(int x, int y) {
return ((x / 3) * 3) + (y / 3);
}
inline void flip(int x, int y, int z) {
row[x] ^= 1 << z;
col[y] ^= 1 << z;
grid[g(x, y)] ^= 1 << z;
}
bool dfs(int now) {
if (now == 0) return 1;
int temp = 10, x, y;
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++) {
if (str[i][j] != '.') continue;
int val = row[i] & col[j] & grid[g(i, j)];
if (!val) return 0;
if (cnt[val] < temp) {
temp = cnt[val];
x = i, y = j;
}
}
int val = row[x] & col[y] & grid[g(x, y)];
for (; val; val -= val&-val) {
int z = num[val&-val];
str[x][y] = '1' + z;
flip(x, y, z);
if (dfs(now - 1)) return 1;
flip(x, y, z);
str[x][y] = '.';
}
return 0;
}
int main() {
for (int i = 0; i < 1 << 9; i++)
for (int j = i; j; j -= j&-j) cnt[i]++; //i二进制下有多少个1
for (int i = 0; i < 9; i++)
num[1 << i] = i; //log运算
char s[100];
while (~scanf("%s", s) && s[0] != 'e') {
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++) str[i][j] = s[i * 9 + j];
for (int i = 0; i < 9; i++) row[i] = col[i] = grid[i] = (1 << 9) - 1;
tot = 0;
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
if (str[i][j] != '.') flip(i, j, str[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] = str[i][j];
puts(s);
}
}