HDU-1426 DFS PE

Problem Description:
填数独
Presentation Error = =
Input
本题包含多组测试,每组之间由一个空行隔开。每组测试会给你一个 9*9 的矩阵,同一行相邻的两个元素用一个空格分开。其中1-9代表该位置的已经填好的数,问号(?)表示需要你填的数。
Output
对于每组测试,请输出它的解,同一行相邻的两个数用一个空格分开。两组解之间要一个空行。
对于每组测试数据保证它有且只有一个解。

Sample Input
7 1 2 ? 6 ? 3 5 8
? 6 5 2 ? 7 1 ? 4
? ? 8 5 1 3 6 7 2
9 2 4 ? 5 6 ? 3 7
5 ? 6 ? ? ? 2 4 1
1 ? 3 7 2 ? 9 ? 5
? ? 1 9 7 5 4 8 6
6 ? 7 8 3 ? 5 1 9
8 5 9 ? 4 ? ? 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
解题思路:
暴力dfs,注意输入输出格式;
代码:

#include<bits/stdc++.h>
#define clr(a,b) memset(a,b,sizeof(a))
using namespace std;
int x[9][10],y[9][10],z[3][3][10],n,p,first=0; //x,y,z分别记录每行每列每个小九宫格的数字出现情况,用空间换时间.62ms
char mp[10][10];
vector<pair<int,int> >q;//记录?位置
void dfs(int xn,int yn,int t){
	if(p)return;
	if(t==n){
		p=1;
		if(first)putchar('\n'); //PE几次才发现最后一组ans后没有空行= =
		for(int i=0;i<9;++i){
			for(int j=0;j<9;++j)
				printf(j==0?"%c":" %c",mp[i][j]);
			putchar('\n');
		}
		first=1;
		return;
	}
	for(int i=1;i<=9;++i)
		if((x[xn][i]||y[yn][i]||z[xn/3][yn/3][i])==0){ //判断该数字可行
			if(p)return;
			x[xn][i]=1;
			y[yn][i]=1;
			z[xn/3][yn/3][i]=1;
			mp[xn][yn]=i+48;
			dfs(q[t+1].first,q[t+1].second,t+1);
			x[xn][i]=0;
			y[yn][i]=0;
			z[xn/3][yn/3][i]=0;
		}

}
int main(){
	while(~scanf(" %c",&mp[0][0])){	//%c前加个空格可以忽略读入字符前的空格,回车制表符
		clr(x,0),clr(y,0),clr(z,0);
		p=0;
		q.clear();
		if(mp[0][0]==63)q.push_back(make_pair(0,0));
		else x[0][mp[0][0]-48] =y[0][mp[0][0]-48] =z[0][0][mp[0][0]-48] =1;
		for(int i=0;i<9;++i)
			for(int j=0;j<9;++j){
				if(i==0&&j==0)continue;
				scanf(" %c",&mp[i][j]);
				if(mp[i][j]==63) q.push_back(make_pair(i,j));
				else x[i][mp[i][j]-48] =y[j][mp[i][j]-48] =z[i/3][j/3][mp[i][j]-48] =1;
			}
		n=q.size();
		dfs(q[0].first,q[0].second,0);
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值