2017年院赛F题 数独游戏

目录:

2017年院赛A题 Neptune'Pudding

2017年院赛B题 N个数求和

2017年院赛C题 treat

2017年院赛D题 简单加密

2017年院赛E题 守望者的逃离

2017年院赛F题 数独游戏

2017年院赛G题 忠诚

2017年院赛H题 最大异或和


题目:

Problem Description

自从2006310日至11日的首届数独世界锦标赛以后,数独这项游戏越来越受到人们的喜爱和重视。

数独游戏的规则是这样的:在一个9x9的方格中,你需要把数字1-9填写到空格当中,并且使方格的每一行和每一列中都包含1-9这九个数字。同时还要保证,空格中用粗线划分成93x3的方格也同时包含1-9这九个数字。比如有这样一个题,大家可以仔细观察一下,在这里面每行、每列,以及每个3x3的方格都包含1-9这九个数字。

Input

第一行输入一个整数T,代表共有T组数据,每组之间由一个空行隔开。每组测试会给你一个 9*9 的矩阵,同一行相邻的两个元素用一个空格分开。其中1-9代表该位置的已经填好的数,数字0表示需要你填的数。

Output

对于每组测试,请输出它的解,同一行相邻的两个数用一个空格分开。两组解之间要一个空行。

对于每组测试数据保证它有且只有一个解。

Sample Input

1

7 1 2 0 6 0 3 5 8

0 6 5 2 0 7 1 0 4

0 0 8 5 1 3 6 7 2

9 2 4 0 5 6 0 3 7

5 0 6 0 0 0 2 4 1

1 0 3 7 2 0 9 0 5

0 0 1 9 7 5 4 8 6

6 0 7 8 3 0 5 1 9

8 5 9 0 4 0 0 2 3

Sample Output

7 1 2 4 6 9 3 5 8

3 6 5 2 8 7 1 9 4

4 9 8 5 1 3 6 7 2

9 2 4 1 5 6 8 3 7

5 7 6 3 9 8 2 4 1

1 8 3 7 2 4 9 6 5

2 3 1 9 7 5 4 8 6

6 4 7 8 3 2 5 1 9

8 5 9 6 4 1 7 2 3


标程:

#include
#include
#include
#include 
using namespace std;

const int MAX=10;
char map_[MAX][MAX];
int pos[MAX*9][2];
bool row[MAX][MAX], list[MAX][MAX];
int k;

bool check(int v,int num)
{
    int n=pos[v][0]/3*3;
    int m=pos[v][1]/3*3;
    for(int i=n;i<n+3;++i)
	{
        for(int j=m;j<m+3;++j)
		{
            if(map_[i][j] == num+'0')return false;
        }
    }
    return true;
}

bool DFS(int v)
{
    if(v == k){return true;}
    for(int i=1;i<10;++i)
	{
        if(!row[pos[v][0]][i] && !list[pos[v][1]][i] && check(v,i)){
            map_[pos[v][0]][pos[v][1]]=i+'0';
            row[pos[v][0]][i]=true;
            list[pos[v][1]][i]=true;
            if(DFS(v+1)){return true;}
            map_[pos[v][0]][pos[v][1]]='?';
            row[pos[v][0]][i]=false;
            list[pos[v][1]][i]=false;
        }
    }
    return false;
}

void output()
{
    for(int i=0;i<9;++i)
	{
        cout<<map_[i][0];
        for(int j=1;j<9;++j)
		{
            cout<<' '<<map_[i][j];
        }
        cout<<endl;
    }
    return;
}

int main()
{
	freopen("1.in" , "r" , stdin);
	freopen("1.out" , "w" , stdout);
	int T;
	scanf("%d", &T);
 int num=0;
 
    while(T--)
	{
		k=0;
		memset(row,false,sizeof row);
		memset(list,false,sizeof list);
		for(int i=0;i<9;++i)
		{
			for(int j=0;j<9;++j)
			{
				if(!(cin>>map_[i][j]))exit(0);
				if(map_[i][j] == '0'){pos[k][0]=i;pos[k++][1]=j;continue;}
				row[i][map_[i][j]-'0']=true;
				list[j][map_[i][j]-'0']=true;
			}
		}
		DFS(0);
		if(num++)cout<<endl;
		output();
    }
    return 0;
} 

我的代码:

#include
using namespace std;

int list[10][10];

bool ok(int i, int j, int k)
{
	for (int jj = 1; jj < 10; jj++)if (list[i][jj] == k)return false;
	for (int ii = 1; ii < 10; ii++)if (list[ii][j] == k)return false;
	int x = (i - 1) / 3 * 3, y = (j - 1) / 3 * 3;
	for (int ii = x + 1; ii <= x + 3; ii++)for (int jj = y + 1; jj <= y + 3;jj++)
		if (list[ii][jj] == k)return false;
	return true;
}

bool trys(int i, int j)
{
	if (j == 10)
	{
		i++;
		j = 1;
	}
	if (i == 10)return true;
	if (list[i][j])return trys(i, j + 1);
	for (int k = 1; k < 10; k++)
	{
		if (ok(i, j, k))
		{
			list[i][j] = k;
			if (trys(i, j + 1))return true;
		}
	}
	list[i][j] = 0;
	return false;
}

void out()
{
	for (int i = 1; i < 10; i++)
	{
		for (int j = 1; j < 9; j++)cout << list[i][j]<<" ";
		cout <<list[i][9]<< endl;
	}
}

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		for (int i = 1; i < 10; i++)for (int j = 1; j < 10; j++)cin >>list[i][j];
		trys(1, 1);
		out();
		cout<<endl;
	}	
	return 0;
}


比赛的时候我带了好多以前打印的博客,其中一篇博客HDU - 1426 Sudoku Killer里面的题目,其实就是这个题目原题。



你可能感兴趣的:(2017年院赛F题 数独游戏)