zoukankan      html  css  js  c++  java
  • POJ 2726、POJ3074 :数独(二进制DFS)

    题目链接:https://ac.nowcoder.com/acm/contest/1014/B

    题目描述

    In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example,

    img

    Given some of the numbers in the grid, your goal is to determine the remaining numbers such that the numbers 1 through 9 appear exactly once in (1) each of nine 3 × 3 subgrids, (2) each of the nine rows, and (3) each of the nine columns.

    输入描述:

    The input test file will contain multiple cases. Each test case consists of a single line containing 81 characters, which represent the 81 squares of the Sudoku grid, given one row at a time. Each character is either a digit (from 1 to 9) or a period (used to indicate an unfilled square). You may assume that each puzzle in the input will have exactly one solution. The end-of-file is denoted by a single line containing the word “end”.

    输出描述:

    For each test case, print a line representing the completed Sudoku puzzle.

    示例1

    输入

    .2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.
    ......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
    end
    

    输出

    527389416819426735436751829375692184194538267268174593643217958951843672782965341
    416837529982465371735129468571298643293746185864351297647913852359682714128574936
    

    分析

    • 可以从左上角一行一行扫描到右下角,对于每一个块列举每一种可能,然后从每个可能出发继续深度遍历直到发现有一个块没有数字可以填时停止
    • 如何储存每一块可以填写的数字?可以利用九位二进制数来表示每一行,每一列,每个九宫格的数字填写情况,然后直接对这三个数字做按位与运算就可以得到某一具体块可以填的数字了。
    • 这里直接用bitset,对于每一个结果,直接遍历一下就可以了。
    #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]++;
    	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++)
    			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);
    	}
    }
    
  • 相关阅读:
    Java 8 新特性-菜鸟教程 (8) -Java 8 日期时间 API
    Java 8 新特性-菜鸟教程 (7) -Java 8 Nashorn JavaScript
    Java 8 新特性-菜鸟教程 (6) -Java 8 Optional 类
    心理相关
    matlab和Visio安装
    论文资料搜集整理(研究现状)
    调式相关
    梅花落与折杨柳
    混合高斯模型——学习笔记
    NSCT,非下采样Contourlet变换——学习笔记
  • 原文地址:https://www.cnblogs.com/RioTian/p/13469483.html
Copyright © 2011-2022 走看看