Description
要求构造一个n×mn×m的括号矩阵,使得合法行与合法列的数量之和最大
Input
第一行一整数TT表示用例组数,每组用例输入两个整数
(1≤T≤50,1≤n,m≤200)(1≤T≤50,1≤n,m≤200)
Output
输出一个n×mn×m的括号矩阵
Sample Input
3
1 1
2 2
2 3
Sample Output
(
()
)(
(((
)))
Solution
显然当n,mn,m全为奇数时每行每列都不会合法,而当两者之中有一个为奇数时就让偶数的行/列合法即可,主要分析两者均为偶数的情况,不妨设n≥mn≥m,给出两种构造方案
1.前n2n2行均为()()...()()()()...()(),后n2n2行均为(()()...()())(()()...()()),容易得知此时每行都合法,而列只有第一列和偶数列不合法,此时合法行列数和为n+m2−1n+m2−1
2.第一行全部为((,最后一行全部为,中间偶数行为()()...()()()()...()(),奇数行为(()()...()())(()()...()()),此时除第一行、第一列、最后一行和最后一列不合法之外其余行列均合法,此时合法行列数为n+m−4n+m−4
当m>6m>6时,若要使得不合法的四个行列中有某行变合法,那么至少也会使得中间已经合法的一行或一列不合法,故最优即为n+m−4n+m−4,而m≤6m≤6时,同样的分析可知n+m2−1n+m2−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;
}