POJ3076 Sudoku
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的更多相关文章
- POJ3076 Sudoku 舞蹈链 DLX
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目(传送门) 题意概括 给出一个残缺的16*16数独,求解. 题解 DLX + 矩阵构建 (两个传送门) 学完这个之后,再 ...
- 【转】Dancing Links题集
转自:http://blog.csdn.net/shahdza/article/details/7986037 POJ3740 Easy Finding [精确覆盖基础题]HUST1017 Exact ...
- dancing links 题集转自夏天的风
POJ3740 Easy Finding [精确覆盖基础题] HUST1017 Exact cover [精确覆盖基础] HDOJ3663 Power Stations [精确覆盖] Z ...
- Sudoku(POJ2676/3074)
Sudoku is one of the metaphysical techniques. If you understand the essence of it, you will have the ...
- Leetcode 笔记 36 - Sudoku Solver
题目链接:Sudoku Solver | LeetCode OJ Write a program to solve a Sudoku puzzle by filling the empty cells ...
- [LeetCode] Sudoku Solver 求解数独
Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...
- [LeetCode] Valid Sudoku 验证数独
Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board could be ...
- LeetCode 36 Valid Sudoku
Problem: Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board ...
- 【leetcode】Valid Sudoku
题目简述: Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board cou ...
随机推荐
- java命令查询属性信息
System.getProperty("user.home")可以查询JAVA系统的user.home属性的值, 除了user.home,还有user.dir, file.sepa ...
- ansible的ad-hoc模式
一.什么是ad-hoc模式 ansible中有两种模式,分别是ad-hoc模式和playbook模式 ad-hoc简而言之,就是"临时命令" 二.ad-hoc模式使用的场景 场景一 ...
- 解题报告Best Time to Buy and Sell Stock with Cooldown
题目 Say you have an array for which the ith element is the price of a given stock on day i. Design an ...
- Maven面试宝典啊
一.Maven有哪些优点和缺点 优点如下: 简化了项目构建.依赖管理: 易于上手,对于新手可能一个"mvn clean package"命令就可能满足他的工作 便于与持续集成工具( ...
- HDFS Hbase
Hbase:Hbase是Hadoop的数据库,是bigtable的实现,基于HDFSHDFS:文件系统,是gfs的实现 Hive,Hbase,HDFS等之间的关系Hive:Hive不支持更改数据的操作 ...
- [C++] Operator Overload
Operator Overload NOTE1: operator = must be overload as a member function NOTE2: An operator functi ...
- itunes win10应用商店安装 升级固件路径
win + r 在运行中输入: %localappdata%\Packages\AppleInc.iTunes_nzyj5cx40ttqa\LocalCache\Roaming\Apple Compu ...
- LWIP带UCOS操作系统移植
LWIP支持RAW.NETCONN.SOCKET这三种编程接口,后两者必须有操作系统来支持的:LWIP带操作系统的移植很重要!!
- 组织机构sql
with cte as ( select vcOrganID, vcParentID, vcOrganName, 0 as lvl from tbOrgan where vcOrgan ...
- 1028 Web Navigation
题目链接: http://poj.org/problem?id=1028 题意: 模拟浏览器的前进/后退/访问/退出 的四个操作. 输出当前访问的URL或者Ignore(如果不能前进/后退). 分析: ...