Analysis of Luogu cf803a maximum binary matrix

Posted by runsum on Sat, 15 Jan 2022 18:31:23 +0100

Source of original title: CodeForces 803A

Title Description:

You are given matrix with n rows and n columns filled with zeroes. You should put k ones in it in such a way that the resulting matrix is symmetrical with respect to the main diagonal (the diagonal that goes from the top left to the bottom right corner) and is lexicographically maximal.

One matrix is lexicographically greater than the other if the first different number in the first different row from the top in the first matrix is greater than the corresponding number in the second one.

If there exists no such matrix then output -1.

Input format:

The first line consists of two numbers n  and k ( 1 <= n <= 100 , 0 <= k <= 10^6 ).

Output format:

If the answer exists then output resulting matrix. Otherwise output -1.

Input and output examples:

Approximate translation:

Give you a matrix with n rows and N columns all 0. You need to put k 1s into the matrix to ensure that the resulting matrix is symmetrical with respect to the main diagonal (the diagonal from the upper left corner to the lower right corner) and that the dictionary order of the matrix is the largest. If such a matrix does not exist, output - 1.

PS (when comparing the dictionary order of two matrices, from the first row to the last row, each row is compared from front to back.)

The comparison of matrix dictionary order is shown in the following figure:

(it is assumed that three 1s are put into a 3 * 3 matrix) the dictionary order of the first matrix is less than that of the second

               1      0      0                                          1      1      0

               0      1      0                                          1      0      0

               0      0      1                                          0      0      0                                

Topic analysis:

From the comparison of dictionary order, we can see that when we put K 1s into the matrix, we should first place them in rows and columns and align them with the main diagonal, and then consider the placement on the diagonal. And when k < n ^ 2, there is no case that K 1s cannot be placed in the matrix of n*n, so - 1 is output only when k > n ^ 2, and the data range given by the topic is not large. The matrix of n*n can use the two-dimensional array of int type, and the placement of 1 can be completed by recursion.

During recursion, we should first analyze and pay attention to the boundary of recursion:

//Function boundary part
#include <iostream>
#include <cstdio>
using namespace std;
int a[100][100] = { 0 };
int i = 0, j = 0;
int n_i = 0;//Current preprocessing line
void place(int n, int k)
{
	if (k == 0)//Returns directly when the remaining k is 0
	{
		return;
	}
	if (k == 1)//When there is only 1 remaining 1 to be filled, fill on the diagonal and return
	{
		a[n_i][n_i] = 1;
		return;
	}
}
//

Specific code (successfully AC):

 

#include <iostream>
#include <cstdio>
using namespace std;
int a[100][100] = { 0 };
int i = 0, j = 0;
int n_i = 0;//Current preprocessing line
void place(int n, int k)//Place k 1s in a matrix of n*n
{
	if (k == 0)
	{
		return;
	}
	if (k == 1)
	{
		a[n_i][n_i] = 1;
	 	return;
	}
	if (k >= 2 * n - 1)//When k > the total number of current rows and columns of the matrix, all the rows and columns are filled with 1
	{
		for (j = n_i; j < n+n_i; j++)
		{
			a[n_i][j] = 1;
			a[j][n_i] = 1;
		}
		n_i++;//Preprocess next line
		return place(n-1, k-(2*n-1));
	}
	else
	{
		for (j = n_i; j < n_i + (k / 2); j++)//Suppose the number of remaining k is even
		{
			a[n_i][j] = 1;
			a[j][n_i] = 1;
		}
		if (k % 2 == 1)//If it is an odd number, fill in the less filled part
		{
			a[n_i][j] = 1;
			a[j][n_i] = 1;
			return place(n, 0);
		}
		else//If the number is even, fill in 1 diagonally
		{
			n_i++;
			return place(n,1);
		}
	}
}
int main()
{
	int n, k;
	cin >> n >> k;
	if (k > n * n)//When the number of k is greater than the total capacity of the matrix
	{
		cout << -1;
		return 0;
	}
	place(n, k);
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < n; j++)
		{
			cout << a[i][j] << " ";
		}
		cout << endl ;
	}
	return 0;
}

 !!! Pay attention to the range of j and the recursive boundary of the function in the loop of the function to avoid less output 1 or repeated assignment and stack overflow. If you are worried that the array is out of bounds, you can expand the range of the array. When submitting questions many times, the editor finds that scanf is not faster than cin, which may be a platform problem. If it times out, you can also try to replace it.

The editor's current level is average. If you have better code, please give me more advice.

Zhang zjr

Topics: C++ Algorithm