代码改变世界

poj 3074,搜索枝剪

2015-08-26 16:21  iun  阅读(260)  评论(0编辑  收藏  举报
Sudoku
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 8909   Accepted: 3196

Description

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

. 2 7 3 8 . . 1 .
. 1 . . . 6 7 3 5
. . . . . . . 2 9
3 . 5 6 9 2 . 8 .
. . . . . . . . .
. 6 . 1 7 4 5 . 3
6 4 . . . . . . .
9 5 1 8 . . . 7 .
. 8 . . 6 5 3 4 .

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.

Input

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”.

Output

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

Sample Input

.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

Sample Output

527389416819426735436751829375692184194538267268174593643217958951843672782965341
416837529982465371735129468571298643293746185864351297647913852359682714128574936

Source

 搜索枝剪,按照每个点的可选择自由度从小到达搜索
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct node{
    int x,y,cnt;
}p[100];
bool cmp(const node& a,const node& b){
    return a.cnt<b.cnt;
}
int g[9][9];
int row[9][10];
int col[9][10];
int cell[9][10];

int getId(int x,int y){
    return (x/3)*3 + y/3;
}

void printans(){
    for(int i=0;i<9;i++){
        for(int j=0;j<9;j++){
            printf("%d",g[i][j]);
        }
//    printf("\n");
    }
    printf("\n");
}

int flag = 1;

int xd[90],yd[90];
void dfs(int n,int m){
    if(n==m){
        flag = 0;
        printans();
        return;
    }
    int small = 10;
    int x,y;
    int idx;
    for(int v =n ;v<m;v++){
        int i = p[v].x, j = p[v].y;
        p[v].cnt = 0;
        for(int k=1;k<=9;k++){
             p[v].cnt += (row[i][k]+col[j][k]+cell[getId(i,j)][k]==0);
        }
        if(p[v].cnt==0)return;
        if(p[v].cnt<small){
              small = p[v].cnt;
              idx = v;
            if(small==1)break;
         }
    }
    if(small==0||small==10) return;    
    swap(p[n],p[idx]);
    x = p[n].x;
    y = p[n].y;
    for(int k=1;k<=9;k++){
        if(row[x][k]+col[y][k]+cell[getId(x,y)][k]==0&&flag){
            g[x][y] = k;
            row[x][k]=col[y][k]=cell[getId(x,y)][k]=1;
            dfs(n+1,m);
            g[x][y] = 0;
            row[x][k]=col[y][k]=cell[getId(x,y)][k]=0;
        }
    }
}

int main(){
    char s[100];
    while(1){
        scanf("%s",s);
        if(s[0]=='e')break;
        memset(row,0,sizeof(row));
        memset(col,0,sizeof(col));
        memset(cell,0,sizeof(cell));
        int ct_zero = 0;
        for(int u=0;u<81;u++)
        {
            int i=u/9;
            int j=u%9;
            if(s[u]>'0'&&s[u]<='9')g[i][j] = s[u]-'0';
            else {
                g[i][j] = 0;
                p[ct_zero].x = i;
                p[ct_zero].y = j;
                ct_zero++;
            }
            row[i][g[i][j]]=1;
            col[j][g[i][j]]=1;
            cell[getId(i,j)][g[i][j]]=1;
        }
        for(int v = 0;v<ct_zero;v++){
            int i = p[v].x, j = p[v].y;
            p[v].cnt = 0;
             for(int k=1;k<=9;k++){
                  p[v].cnt += (row[i][k]+col[j][k]+cell[getId(i,j)][k]==0);
             }
         }
        sort(p,p+ct_zero,cmp);
        flag = 1;
        dfs(0,ct_zero);    
    }
    return 0;
}