80分死都过不去。。
查看原帖
80分死都过不去。。
138608
白格Lifeplayer楼主2021/9/19 15:38

之前第2个点A了其他WA了。现在改改第2个点WA了,其他点A了。。。。。。


 void prt()
 {//用来输出方格的样子的函数
 	for(int i=1;i<=n;i++){
 		for(int j=1;j<=n;j++)
 		{if(j!=n)cout << ans[i][j] << ' ';
      else cout << ans[i][j]<< endl; }}
	 cout << endl;
  }

void dfs(int x, int y)
{
	int dx, dy,s;
	if(y==n && suml[x]!=sum)return ;//如果到头了总和不对就剪枝
	if(y==n && x==n && sumx2!=sum)return ;//如果到了右下角对角线和不对就回去
	if(y==1 && x==n && sumx1!=sum)return ;//如果到了左下角对角线和不对就回去
	if(x==n && sumr[y]!=sum)return ;//如果到了最后一行,检验列的和
	if(x==n && y==n){j=1;return;}//到了最后,啥都行了,可以回溯到主函数了
	if(y==n)dx=x+1,dy=1;
	else dx=x,dy=y+1;//算出下一个遍历的位置
	int i;
	for(i=1;i<=N;i++)
	{//遍历可以用的数
		if(!mrk[i])//如果该数没用过
		{
			s=sto[i];//记录当前遍历点的值
			suml[dx]+=s;//算行的总和
			sumr[dy]+=s;//算列的总和
			if(dx+dy-1==n)sumx1+=s;
			if(dx-dy+n==n)sumx2+=s;//如果点在对角线上就加上
			mrk[i]=1;//标记当前点用了
			ans[dx][dy]=s;//记录答案的方块长啥样
			dfs(dx,dy);
			if(j)return;//得出答案后快速回溯
			ans[dx][dy]=0;
			mrk[i]=0;
			suml[dx]-=s;
			sumr[dy]-=s;
			if(dx+dy-1==n)sumx1-=s;
			if(dx-dy+n==n)sumx2-=s;
			//以上六行都是dfs后用于复原的
		}
	}
}

int main()
{
	cin >> n;
	N =n*n;//算出总的数的个数
	for(int i=1;i<=N;i++)
	{
		cin >> sto[i];
		sum+=sto[i];
	}
	sum=sum/n;//算出sum的值
	sort(sto+1,sto+1+N);
	memset(mrk,0,sizeof(mrk));
	dfs(1, 0);
	cout << sum << endl;
	prt();
	return 0;
}

2021/9/19 15:38
加载中...