2012第三届蓝桥杯C本科决赛 第五题 “数独”游戏

本文介绍了一个使用C语言实现的回溯法求解特定问题的例子。该程序通过定义结构体来组织数据,并利用递归回溯的方法尝试所有可能的组合方案,最终输出所有符合条件的解。代码详细展示了如何进行冲突检测以及状态恢复。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <stdio.h>
int all; // 解答计数

// 保存组别和已设置字符
struct Mar{
	char group;
	char set;
}mar[6][6];

// 将组和行列分离判断
struct Group{
	int count; // 记录指针
	char set[6]; // 组内字符
}grp[6];

// 行列是否重复
int lc(int m, int n, char c){ 
	int i;
	for(i=0; i<6; i++){
		if(mar[m][i].set==c)
			return 0;
	}
	for(i=0; i<6; i++){
		if(mar[i][n].set==c)
			return 0;
	}
	return 1;
}

// 处理grp数组,判断组内是否重复
int gp(char gr, char c){
	int i;
	for(i=0; i<grp[gr-'0'].count; i++){
		if(c==grp[gr-'0'].set[i])
			return 0;
	}
	return 1;
}

// 打印
void print(){
	printf("%d\n", ++all);
	int i, j;
	for(i=0; i<6; i++){
		for(j=0; j<6; j++) printf("%c ", mar[i][j].set);
		printf("\n");
	}
}

// 回溯函数,试探赋值
void set(int m, int n){
	// 满足输出
	if(m>5){
		print();
		return;
	}

	int i;

	// 区分固定已设置字符和可变动字符
	if(mar[m][n].set=='0'){
		for(i=0; i<6; i++){
			if(lc(m, n, i+'A') && gp(mar[m][n].group, i+'A')){ // 判断
				mar[m][n].set=i+'A'; // 试探
				grp[mar[m][n].group-'0'].set[grp[mar[m][n].group-'0'].count++]=mar[m][n].set; // 对应组增加一个字符

				set(m+(n+1)/6, (n+1)%6);
				//mar[m][n].set='0'; //函数退出时必须还愿状态,由于不参与条件判断,常放于函数后面
				grp[mar[m][n].group-'0'].set[--(grp[mar[m][n].group-'0'].count)]='0'; // 注意组设置字符时会影响下次试探的判断所以必须还原
			}
		}
		mar[m][n].set='0';
	}
	else set(m+(n+1)/6, (n+1)%6);
}

int main(){
	int i, j, n, t;
	char c;
	for(i=0; i<6; i++){
		for(j=0; j<6; j++){
			mar[i][j].group=getchar();
			mar[i][j].set='0';
		}
		getchar();
	}
	scanf("%d", &n);
	while(n--){
		scanf("%d%c", &t,&c);
		mar[t/10][t%10].set=c;
		grp[mar[t/10][t%10].group-'0'].set[(grp[mar[t/10][t%10].group-'0'].count++)]=c;
	}
	set(0,0);
	if(all==0) printf("0\n");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值