P1406 方格填数

文章讲述了如何使用深度优先搜索(DFS)算法解决给定n×n矩阵中整数填充问题,确保每行、每列和两条对角线的和相等。通过剪枝优化,找到字典序最小的解,并对输入数据进行排序以提高效率。

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

题目描述

给一个 n×n 的方格矩阵,还有 n×n 个整数,让你将这些整数填入矩阵,使得每行每列每个对角线上整数的和都相等。下面给出几个例子:

输入格式

第一行一个整数 n (1≤n≤4)。

第二行n×n 个整数 ​ (−108≤ai​≤108)。

输出格式

第一行一个整数 s 代表每行每列每个对角线的和值。

接下来输出一个 n×n 的矩阵,表示填数方案。

数据保证有解,可能存在多种方案,输出字典序最小的(将每行顺次相连之后,字典序最小)

输入输出样例

输入 

3
1 2 3 4 5 6 7 8 9

输出 

15
2 7 6
9 5 1
4 3 8

说明/提示

数据范围及约定

对于80% 的数据,保证 1≤n≤3;

对于100% 的数据,保证 1≤n≤4。

注意

方法是dfs

剪枝:填到每一行、每一列最后一个数字时判断是否合法,速度能快很多

输出时要输出字典序最小的,所以一开始要把输入数据排序。

#include<bits/stdc++.h>
using namespace std;
int n,a[101],z=0,f[101],ans[11][11];
void s(int x,int y){
	if(x==n&&y==n+1){//找到目标解,输出 
		cout<<z<<endl;
		for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(j==n) cout<<ans[i][j]<<endl; else cout<<ans[i][j]<<" ";
		exit(0);//直接结束程序 
	}
	if(y>n){//下一行 
		s(x+1,1);
		return;
	}
	for(int i=1;i<=n*n;i++)if(f[i]==0){//未使用 
		if(y==n){//行判断 
			int u=a[i];
			for(int j=1;j<n;j++) u+=ans[x][j];
			if(u!=z) continue;
		}
		if(x==n){//列判断 
			int u=a[i];
			for(int j=1;j<n;j++) u+=ans[j][y];
			if(u!=z) continue;
		}
		if(x==n&&y==1){//斜线(右上角到左下角) 
			int u=a[i];
			for(int j=1;j<n;j++) u+=ans[j][n-j+1];
			if(u!=z) continue;
		}
		if(x==n&&y==n){//斜线(左上角到右下角)
			int u=a[i];
			for(int j=1;j<n;j++) u+=ans[j][j];
			if(u!=z) continue;
		}
		f[i]=1;
		ans[x][y]=a[i];
		//标记 
		s(x,y+1);
		f[i]=0;
		//清除标记 
	}
}
int main(){
    cin>>n;
    for(int i=1;i<=n*n;i++) cin>>a[i],z+=a[i];
    z/=n;//算出每行每列每个对角线上的整数 
    sort(a+1,a+n*n+1);//sort快排 
    s(1,1);
    return 0;
}

嘿嘿,我的代码风格就总变,今天想这么写,明天想那么写······

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值