Description
要求构造一个 n×m n × m 的括号矩阵,使得合法行与合法列的数量之和最大
Input
第一行一整数 T T 表示用例组数,每组用例输入两个整数
(1≤T≤50,1≤n,m≤200) ( 1 ≤ T ≤ 50 , 1 ≤ n , m ≤ 200 )
Output
输出一个 n×m n × m 的括号矩阵
Sample Input
3
1 1
2 2
2 3
Sample Output
(
()
)(
(((
)))
Solution
显然当 n,m n , m 全为奇数时每行每列都不会合法,而当两者之中有一个为奇数时就让偶数的行/列合法即可,主要分析两者均为偶数的情况,不妨设 n≥m n ≥ m ,给出两种构造方案
1.前 n2 n 2 行均为 ()()...()() ( ) ( ) . . . ( ) ( ) ,后 n2 n 2 行均为 (()()...()()) ( ( ) ( ) . . . ( ) ( ) ) ,容易得知此时每行都合法,而列只有第一列和偶数列不合法,此时合法行列数和为 n+m2−1 n + m 2 − 1
2.第一行全部为 ( ( ,最后一行全部为,中间偶数行为 ()()...()() ( ) ( ) . . . ( ) ( ) ,奇数行为 (()()...()()) ( ( ) ( ) . . . ( ) ( ) ) ,此时除第一行、第一列、最后一行和最后一列不合法之外其余行列均合法,此时合法行列数为 n+m−4 n + m − 4
当 m>6 m > 6 时,若要使得不合法的四个行列中有某行变合法,那么至少也会使得中间已经合法的一行或一列不合法,故最优即为 n+m−4 n + m − 4 ,而 m≤6 m ≤ 6 时,同样的分析可知 n+m2−1 n + m 2 − 1 为最大合法行列数
Code
#include<cstdio>
#include<algorithm>
using namespace std;
int T,n,m;
char a[205][205];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
int flag=0;
if(n<m)swap(n,m),flag=1;
if(n&1)
{
if(m&1)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
a[i][j]='(';
}
else
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(j&1)a[i][j]='(';
else a[i][j]=')';
}
}
else
{
if(m&1)
{
for(int j=1;j<=m;j++)
for(int i=1;i<=n;i++)
if(i&1)a[i][j]='(';
else a[i][j]=')';
}
else if(m==2)
{
for(int i=1;i<=n;i++)a[i][1]='(',a[i][2]=')';
}
else if(m<=6)
{
for(int i=1;i<=n/2;i++)
for(int j=1;j<=m;j++)
if(j&1)a[i][j]='(';
else a[i][j]=')';
for(int i=n/2+1;i<=n;i++)
{
a[i][1]='(';a[i][m]=')';
for(int j=2;j<m;j++)
if(j&1)a[i][j]=')';
else a[i][j]='(';
}
}
else
{
for(int j=1;j<=m;j++)a[1][j]='(',a[n][j]=')';
for(int i=2;i<n;i++)
if(i&1)
{
for(int j=1;j<=m;j++)
if(j&1)a[i][j]='(';
else a[i][j]=')';
}
else
{
a[i][1]='(';a[i][m]=')';
for(int j=2;j<m;j++)
if(j&1)a[i][j]=')';
else a[i][j]='(';
}
}
}
if(!flag)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
printf("%c",a[i][j]);
printf("\n");
}
}
else
{
for(int j=1;j<=m;j++)
{
for(int i=1;i<=n;i++)
printf("%c",a[i][j]);
printf("\n");
}
}
}
return 0;
}