P1406

方格填数

题目描述

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

2 7 6
9 5 1
4 3 8

输入格式

输入格式

第一行一个整数n.(1<=n<=4)

第二行n*n个整数 ai (-108<=ai<=108)

输出格式

输出格式

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

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

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

样例 #1

样例输入 #1

3
1 2 3 4 5 6 7 8 9

样例输出 #1

15
2 7 6
9 5 1
4 3 8

提示

数据范围

80% 1<=n<=3

100%1<=n<=4

服了 这题要求字典序最小 所以要先sort!!!
然后n=4不剪枝必TLE 
只用加一个小优化即可 记录每行的和 若某行的和!=tot 则return
还要发现tot是可以提前算出来的
(这个P题卡了我好久……)
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,tot,a[105],vis[105],jl[15][15],heng[10];
bool check()
{
	int s=0;
	for(int i=1;i<=n;i++)
	{
		s=0;
		for(int j=1;j<=n;j++)
			s+=jl[i][j];		
		if(s!=tot)return false;
	}
	for(int i=1;i<=n;i++)
	{
		s=0;
		for(int j=1;j<=n;j++)
			s+=jl[j][i];		
		if(s!=tot)return false;
	}
	s=0;
	for(int i=1;i<=n;i++)s+=jl[i][i];
	if(s!=tot)return false;
	s=0;
	for(int i=1;i<=n;i++)s+=jl[i][n+1-i];
	if(s!=tot)return false;
	return true;
}
void dfs(int x,int y)
{
	if(x==n+1&&y==1)
	{
		if(check())
		{
			cout<<tot<<"\n";
			for(int i=1;i<=n;i++)
			{
				for(int j=1;j<=n;j++)
					cout<<jl[i][j]<<" ";
				cout<<"\n";
			}
			exit(0);
		}
		return ;
	}
	if(x>1)
	{
		if(heng[x-1]!=tot)return ;
	}
	for(int i=1;i<=n*n;i++)
	{
		if(!vis[i])
		{
			jl[x][y]=a[i];
			heng[x]+=a[i];
			vis[i]=1;
			if(y==n)dfs(x+1,1);
			else dfs(x,y+1);
			jl[x][y]=0;
			heng[x]-=a[i];
			vis[i]=0;
		}
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin>>n;
	for(int i=1;i<=n*n;i++)
	{
		cin>>a[i];
		tot+=a[i];
	}
	sort(a+1,a+n*n+1);
	tot/=n;
	dfs(1,1);
	return 0;
}
posted @ 2023-01-09 11:48  PKU_IMCOMING  阅读(28)  评论(0)    收藏  举报