D. Grid-00100(构造一个行列均匀的方阵)

Problem - 1371D - Codeforces

题意:

你得到的是整数n,k。构建一个大小为n×n的网格A,由整数0和1组成。应该满足一个非常重要的条件:网格中所有元素的总和正好为k。

我们来定义一下。

Ai,j为第i行和第j列的整数。
Ri=Ai,1+Ai,2+...+Ai,n(对于所有1≤i≤n)。
Cj=A1,j+A2,j+...+An,j(对于所有1≤j≤n)。
换句话说,Ri是网格A的行和,Cj是列和。 
对于网格A,让我们定义值f(A)=(max(R)-min(R))2+(max(C)-min(C))2(这里对于一个整数序列X,我们定义max(X)为X中的最大值,min(X)为X的最小值)。
找到任何满足以下条件的网格A。在这样的网格中找到任何一个,对于它来说,f(A)的值是可能的最小值。在这样的表格中,你可以找到任何一个。

输入
输入由多个测试案例组成。第一行包含一个整数t(1≤t≤100)--测试案例的数量。接下来的t行包含测试用例的描述。

对于每个测试案例,唯一的一行包含两个整数n,k(1≤n≤300,0≤k≤n2)。

保证所有测试用例的n2之和不超过105。

输出
对于每个测试案例,首先打印所有表格中f(A)的最小可能值,对该条件的满足。

然后,打印n行,每行包含n个字符。第i行中的第j个字符应该等于Ai,j。

如果有多个答案,你可以打印任何一个。

题解:

题意已经说的很明确了,让(每行最大最小与的差值平方  + 每列最大最小的差值平方)最小

所以我们应构建一个均匀的矩阵,

剩下就是如何构造了

这是其中一种构造方法

 

#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;

int a[305][305];
void solve()
{
	int n,k;
	cin >> n >> k;
	memset(a,0,sizeof a);
	int t = 1; 
	while(k)
	{
		for(int i = t;i <= n;i++)
		{
			if(a[i][i-t+1]==0&&k)
			{
				a[i][i-t+1] =1;
				k--;
			}
		}
		for(int j = 1;j < t;j++)
		{
			if(a[j][n-t+j+1]==0&&k)
			{
				a[j][n-t+j+1] = 1;
				k--;
			}
		}
		t++;
	}
	int ans = 0,l1 = n+1,l2 = n+1,r1 = 0,r2 =0;
	for(int i = 1;i <= n;i++)
	{
		int s1 = 0,s2 = 0;
		for(int j = 1;j <= n;j++)
		{
			s1 += a[i][j];
			s2 += a[j][i];
		}
		l1 = min(s1,l1);
		r1 = max(s1,r1);
		l2 = min(s2,l2);
		r2 = max(s2,r2);
	}
	ans = (r1 - l1)*(r1 - l1)+(r2 - l2)*(r2 - l2);
	cout<<ans<<"\n";
	for(int i = 1;i <= n;i++)
	{
		for(int j = 1;j <= n;j++)
		cout<<a[i][j];
		cout<<"\n";
		
	}
}
int main()
{
	int t;
	cin >> t;
	while(t--)
	{
		solve();
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值