POJ3076 Sudoku

  • 本题为16*16宫格
  • 剪枝见代码
 #include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=; #define res register int
int map[N][N];
unsigned short t[N][N];
//table[i,j](二进制)表示(i,j)可以填的数,0可填,1不可填
int filled(); inline void my_fill(int x,int y,int a)//(x,y)填a
{
filled++;
map[x][y]=a;
t[x][y] |=<<(a-);
for(res i= ; i< ; i++)
t[x][i] |=<<(a-),
t[i][y] |=<<(a-);
int r=x/*,c=y/*;//(r,c)表示(x,y)所在的16宫格的左上角的格子,(从(0,0)开始)
for(res i= ; i< ; i++)
for(res j= ; j< ; j++) t[r+i][j+c] |=<<(a-);
} //判断x中0的个数是否只有1个
int count_zero(unsigned short x)
{
int p(-);
for(int i=;x;i++)
{
if(x&==)
{
if(p!=-) return -;
p=i;
}
x>>=;
}
return p;
} //第x行,数字k+1,返回>0表示唯一可填的k+1的位置,-1表示有多个可以填的位置或已经填过,-2不能填
inline int col(int x,int k)
{
int p(-);
for(res y= ; y< ; y++)
{
if(map[x][y]==k+) return -;//已经填过
if(map[x][y]>) continue;
if((t[x][y]&(<<k))==)
{
if(p!=-) return -;//多次出现
p=y;
}
}
if(p!=-) return p;
return -;
} //第y列,数字k
inline int row(int y,int k)
{
int p=-;
for(res x= ; x< ; x++)
{
if(map[x][y]==k+) return -;
if(map[x][y]>) continue;
if((t[x][y]&(<<k))==)
{
if(p!=-) return -;
p=x;
}
}
if(p!=-) return p;
return -;
} inline void grid(int r,int c,int k,int &x,int &y)
//以(r,c)为左上角的16宫格,数字k+1,(x,y)为唯一可填坐标[
{
x=-;
for(res i= ; i< ; i++)
for(res j= ; j< ; j++)
{
if(map[r+i][c+j]==k+) {x=-; return ;}
if(map[r+i][c+j]>) continue;
if((t[r+i][c+j]&(<<k))==)
{
if(x!=-) {x=-; return ;}
x=i,y=j;
}
}
} inline int count_1(unsigned short x) {
int tmp();
while(x) {
if(x&) tmp++;
x>>=;
}
return tmp;
} bool search()
{
if(filled==) return true;
//先看是否有能确定的格子
for(res x= ; x< ; x++)
for(res y= ; y< ; y++)
{
if(map[x][y]>) continue;
int k=count_zero(t[x][y]);
if(k!=-) my_fill(x,y,k+);
}
for(res x= ; x< ; x++)
for(res k= ; k< ; k++)
{
int y=col(x,k);
if(y==-) return false;
if(y!=-) my_fill(x,y,k+);
}
for(res y= ; y< ; y++)
for(res k= ; k< ; k++)
{
int x=row(y,k);
if(x==-) return false;
if(x!=-) my_fill(x,y,k+);
}
for(res r= ; r< ; r+=)
for(res c= ; c< ; c+=)
for(res k= ; k< ; k++)
{
int x,y;
grid(r,c,k,x,y);
if(x==-) return false;
if(x!=-) my_fill(r+x,c+y,k+);
}
if(filled==) return true;
int t_filled(filled);
int t_map[N][N];
unsigned short t_t[N][N];
for(res i= ; i< ; i++)
for(res j= ; j< ; j++)
t_map[i][j]=map[i][j],
t_t[i][j]=t[i][j];
//找可能情况最少的格子来枚举
int mx,my,mn=;
for(res i= ; i< ; i++)
for(res j= ; j< ; j++)
{
if(map[i][j]>) continue;
int r=-count_1(t[i][j]);
//未确定的
if(r<mn)
{
mn=r; mx=i; my=j;
}
}
for(res k= ; k< ; k++)
if((t[mx][my]&<<k)==)
{
my_fill(mx,my,k+);
if(search()) return true;
filled=t_filled;
for(res i= ; i< ; i++)
for(res j= ; j< ; j++)
map[i][j]=t_map[i][j],
t[i][j]=t_t[i][j];
}
return false;
} char ar[N];
int main()
{
while()
{
filled=;
memset(map,,sizeof(map)); memset(t,,sizeof(t));
for(int i= ; i< ; i++)
{
if(scanf("%s",ar)==EOF) return ;
for(int j= ; j< ; j++)
if(ar[j]!='-') my_fill(i,j,ar[j]-'A'+);
}
search();
for(res i= ; i< ; i++)
{
for(res j= ; j< ; j++) printf("%c",map[i][j]+'A'-);
puts("");
}
puts("");
}
return ;
}

POJ3076 Sudoku的更多相关文章

  1. POJ3076 Sudoku 舞蹈链 DLX

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目(传送门) 题意概括 给出一个残缺的16*16数独,求解. 题解 DLX + 矩阵构建  (两个传送门) 学完这个之后,再 ...

  2. 【转】Dancing Links题集

    转自:http://blog.csdn.net/shahdza/article/details/7986037 POJ3740 Easy Finding [精确覆盖基础题]HUST1017 Exact ...

  3. dancing links 题集转自夏天的风

    POJ3740     Easy Finding [精确覆盖基础题] HUST1017    Exact cover [精确覆盖基础] HDOJ3663 Power Stations [精确覆盖] Z ...

  4. Sudoku(POJ2676/3074)

    Sudoku is one of the metaphysical techniques. If you understand the essence of it, you will have the ...

  5. Leetcode 笔记 36 - Sudoku Solver

    题目链接:Sudoku Solver | LeetCode OJ Write a program to solve a Sudoku puzzle by filling the empty cells ...

  6. [LeetCode] Sudoku Solver 求解数独

    Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...

  7. [LeetCode] Valid Sudoku 验证数独

    Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board could be ...

  8. LeetCode 36 Valid Sudoku

    Problem: Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board ...

  9. 【leetcode】Valid Sudoku

    题目简述: Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board cou ...

随机推荐

  1. iOS导航栏自由缩放头像效果

    效果图: 上代码: 先给一个self.navigationItem.titleView ,然后再放个ImangeView添加到titleView上: UIView *titleView = [[UIV ...

  2. Ubuntu设置屏幕分辨率

    Ubuntu设置屏幕分辨率 原创 2016年10月14日 13:01:24 14900 在虚拟机装好Ubuntu,进入系统分辨率是800*600,打开显示界面设置下分辨率,设置完怎么也选不上应用,于是 ...

  3. 相机IMU融合四部曲(二):误差状态四元数详细解读

    相机IMU融合四部曲(二):误差状态四元数详细解读 极品巧克力 前言 上一篇文章,<D-LG-EKF详细解读>中,讲了理论上的SE3上相机和IMU融合的思想.但是,还没有涉及到实际的操作, ...

  4. TF录像存储专项测试

    测试环境 移动设备:小米4C 移动设备版本:Android 5.1 IPC版本号:0.1.4110_10.1.1.1.3948 安居小宝版本:Version:2.0.1 测试网络:IPC使用WIFI网 ...

  5. 1083 Moving Tables

    题目链接:http://poj.org/problem?id=1083 题意: 走廊两边分别有200个房间,一边连续编号为1-399的奇数,另一边是2-400的偶数, 如果从房间 i 移动桌子到房间 ...

  6. Yii项目开发总结

    学习Yii很久了,一直做的是小案例,自以为学的还不错.直到最近用Yii开发了一个非常简单的CMS,一路下来,磕磕绊绊,才知自己不足.加上最近正学习着偏架构方面的知识.特此总结一下.小白经验,大神轻拍, ...

  7. HDU 4714 Tree2cycle (树形DP)

    题意:给定一棵树,断开一条边或者接上一条边都要花费 1,问你花费最少把这棵树就成一个环. 析:树形DP,想一想,要想把一棵树变成一个环,那么就要把一些枝枝叶叶都换掉,对于一个分叉是大于等于2的我们一定 ...

  8. Web大文件上传(断点续传)控件-Xproer.HttpUploader6-安装教程

      安装教程: IE8控件安装教程 IE9控件安装教程 Firefox控件安装教程 Chrome控件安装教程 Chrome 45+控件安装教程 相关问题: 提示Runtime Error错误 360拦 ...

  9. shell 编程 变量

    转自:http://blog.csdn.net/qq504196282/article/details/52994249 shell之变量和引用 分类:SHELL编程基础 (470)  (0)  举报 ...

  10. TangoAreaDescriptionMetaData区域描述元数据

    TangoAreaDescriptionMetaData com.google.atap.tangoservice Class TangoAreaDescriptionMetaData java.la ...