洛谷P1074靶形数独题解--zhengjun

题面传送门

思路

一看就是一道搜索的好题目。

说道搜索,就想到了剪枝优化,然后,可以想到一个很简单的剪枝,就是先选所在的行、列、宫已知的数字最多的格子,这样有点麻烦,我就直接看看行就完事了。

然后,然后就是一个搜索了。

代码

#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define abs(x) ((x)>0?(x):-(x))
using namespace std;
int a[10][10];
int h[10][10],l[10][10],g[10][10];//记录行列宫的每个数填了没有
int k[100][2],tot;//记录没有填的格子的行列
int sum;
int get(int i,int j){
	return (i-1)/3*3+(j-1)/3+1;
}
int f(int i,int j){
	return 10-max(abs(i-5),abs(j-5));
}
struct zj{
	int i,sum;
	bool operator < (const zj &x)const{
		return sum>x.sum;
	}
}line[10];
int ans=-1;
void dfs(int x,int y){
	if(x==tot+1){//所有的都填完了
		ans=max(ans,y);
		return;
	}
	for(int i=1;i<=9;i++){
		if(!h[k[x][0]][i]&&!l[k[x][1]][i]&&!g[get(k[x][0],k[x][1])][i]){
			h[k[x][0]][i]=l[k[x][1]][i]=g[get(k[x][0],k[x][1])][i]=1;
			dfs(x+1,y+f(k[x][0],k[x][1])*i);
			h[k[x][0]][i]=l[k[x][1]][i]=g[get(k[x][0],k[x][1])][i]=0;//回溯
		}
	}
}
int main(){
	for(int i=1;i<=9;i++){
		line[i].i=i;
		for(int j=1;j<=9;j++){
			scanf("%d",&a[i][j]);
			if(a[i][j])
			h[i][a[i][j]]=l[j][a[i][j]]=g[get(i,j)][a[i][j]]=1,sum+=f(i,j)*a[i][j];
			line[i].sum+=bool(a[i][j]);
		}
	}
	sort(line+1,line+1+9);
	for(int i=1;i<=9;i++){
		for(int j=1;j<=9;j++){
			if(!a[line[i].i][j]){
				k[++tot][0]=line[i].i;k[tot][1]=j;
			}
		}
	}
	dfs(1,sum);
	printf("%d",ans);
	return 0;
}

谢谢–zhengjun

您好!对于解决数独问题,可以使用整数规划模型来表示。以下是针对数独问题的一个简化的整数规划模型示例: 1. 定义变量: - 令 x(i, j, k) 表示数独中第 i 行、第 j 列的单元格是否填入数字 k。如果 x(i, j, k) = 1,则表示填入数字 k;如果 x(i, j, k) = 0,则表示不填入数字 k。 2. 定义约束条件: - 每个单元格只能填入一个数字:对于每个单元格 (i, j),约束条件为 ∑(k=1 to 9) x(i, j, k) = 1。 - 每一行只能包含每个数字一次:对于每个 i 和 k,约束条件为 ∑(j=1 to 9) x(i, j, k) = 1。 - 每一列只能包含每个数字一次:对于每个 j 和 k,约束条件为 ∑(i=1 to 9) x(i, j, k) = 1。 - 每个九宫格只能包含每个数字一次:对于每个九宫格起始单元格的坐标 (a, b) 和 k,约束条件为 ∑(i=a to a+2, j=b to b+2) x(i, j, k) = 1。 - 已给出的初始数字:对于已经给出的初始数字,约束条件为 x(i, j, k) = 1,其中 (i, j) 为初始数字的位置,k 为初始数字的值。 3. 定义目标函数: - 由于数独问题是一个求解问题,没有明确的目标函数。可以将目标函数定义为空,或者根据需要设置一些特定的目标,如最小化某个变量的值等。 以上是一个简化的整数规划模型示例,您可以根据实际情况进行调整和扩展。在使用MATLAB进行求解时,可以使用线性规划工具箱中的整数规划函数进行求解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A_zjzj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值