题目大意
给你一个 n × n n \times n n×n 的矩阵,问能否通过重新排列矩阵的数字,使每一列没有同样的数字。
思路
如果要每一列都没有相同的数字,那么每种数字出现的次数肯定不比 n n n 大。
首先可以定义两个数组,一个用来放数字,一个求次数。
其次定义一个变量 f f f 用来表示目前已经输入了几个不同的数。
接着我写了一个函数用来判断一个数字是否在数组中出现过,是返回是第几项,否则返回 0 0 0。
最后循环一遍,判断有没有数字超出 n n n。
证明每种数字出现的次数 $ \leq n$
如果证明每种数字出现的次数 $ > n$,那么按照最平均的方法,每列放一个,还是会剩余最少一个数字无处可放
例如这个
3
×
3
3 \times 3
3×3 的矩阵
1 | 2 | 3 |
---|---|---|
1 | 2 | 3 |
3 | 1 | 1 |
将其按照最平均的方法排列后:
1 | 1 | 1 |
---|---|---|
1 | 3 | 2 |
3 | 2 | 3 |
无论如何都有一个 1 1 1 会重复
代码
(建议自己根据思路编写程序,有遇到困难再来看代码)
#include<bits/stdc++.h>
using namespace std;
int t,n,k;
int f = 0;
int a[10202],b[10202];//a 表示数字,b 表示次数
int find(int l) {//判断之前这个数字有没有在数组里出现过
for(int i = 1;i <= f;i++) {
if(a[i] == l) {
return i; //如果有,返回是第几个出现的
}
}
return 0;//否则返回0
}
int main() {
scanf("%d",&t);;
for(int i = 1;i <= t;i++) {
scanf("%d",&n);
for(int j = 1;j <= n * n;j++) {
scanf("%d",&k);//每次读入一个数即可
if(find(k)) {
b[find(k)] ++;//找得到,对应数字个数加1
}
else{
//找不到,创建一个数字
f++;
a[f] = k;
b[f] = 1;
}
}
bool s = 1;
for(int j = 1;j <= f;j++) {
if(b[j] > n) {
s = 0;
printf("Case %d: no\n",i);//输出no
break;
}
}
if(s) {
printf("Case %d: yes\n",i);//输出yes
}
f = 0;//注意f要重置,不然会出错
}
}