z z q zzq zzq 喜欢构造题,于是又出了一道构造题。
你需要构造一个 n × n n\times n n×n的矩阵,每个格子里你需要填一个 1 ∼ n 2 1∼n^2 1∼n2 的整数。你需要保证第 i i i 行恰好有 a i a_i ai 个不同的数,第 i i i 列恰好有 b i b_i bi 个不同的数,其中 a i , b i ∈ [ 2 , n ] a_i,b_i\in[2,n] ai,bi∈[2,n]
如果有解,给出任意一个解。如果无解,输出 − 1 −1 −1。
盲猜有解
真实的构造题,做法就是先给主对角线填上 1 1 1 ,再给任意一条副对角线填上不同的 i i i。
这样可以保证行列都至少有两个了,接下来一个一个位置填,如果行列都有剩余,那么填一个新的数,否则如果行有剩余,那么就填列的特有数,反之同理,如果行列都没有剩余,就填 1 1 1 ,那么就做完了。
#include<bits/stdc++.h>
using namespace std;
const int N=310;
int n,a[N],b[N],d[N][N],h[N],l[N];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]-=2;
for(int i=1;i<=n;i++) scanf("%d",&b[i]),b[i]-=2;
for(int i=1;i<=n;i++) d[i][i]=1;
for(int i=1;i<n;i++) h[i]=i+1,l[i+1]=i+1,d[i][i+1]=i+1;
h[n]=n+1;l[1]=n+1;d[n][1]=n+1;
int tot=n+1;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++) if(!d[i][j]){
if(a[i] && b[j]){
a[i]--;b[j]--;
d[i][j]=++tot;
}
else if(b[j]) d[i][j]=h[i],b[j]--;
else if(a[i]) d[i][j]=l[j],a[i]--;
else d[i][j]=1;
printf("%d ",d[i][j]);
}
else printf("%d ",d[i][j]);
printf("\n");
}
}