题目传送门
题意:
题目就是给你一组序列要你利用这些数构造出一个上下对称,左右也对称的n*n矩阵。若不能,输出NO,否则输出YES,并输出够早的矩阵。
思路:
比赛的时候,自己求快,稍微有点头目就开始动笔,不愿意继续深入归纳(自己有点懒)。结果就是调试爆炸,代码超长。写出了一个垃圾代码。
像这种构造体,或者模拟题,一定要去找到不同情况之间的共性。归纳他们的相同点和不同点。比如这里分为n为奇数和偶数两种情况。偶数简单,开始分成4块,用数字填写那对称的4块时,他们两个可以共用一些代码。
下面n为奇数时,要特别处理中间的,中间的至少要2个,中心1个。对称的4块要4个。
还有就是找数,可以用一个通用函数get_sum,不管找几个,只要找到后,就把相应的数的次数减去相应的个数,然后返回。找不到就返回NO的标记值。
自己的思维还是局限,没有养成抽象的习惯,总是翻译简单易懂的逻辑,没有用另一种稍微转一下弯的逻辑(旺旺可以简化代码,减低出错率)。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
typedef long long LL;
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define mem(a,b) memset(a,b,sizeof(a))
#define per(i,a,b) for(int i = a;i <= b;++i)
#define rep(i,a,b) for(int i = a;i >= b;--i)
const int maxn = 20;
int n = 0,m = 0;
map<int,int> mp;
int a[maxn+10][maxn+10];
int get_num(int cnt){
map<int,int>::iterator it = mp.begin();
for(it = mp.begin();it != mp.end();++it){
if(it->second >= cnt){
it->second -= cnt;
return it->first;
}
}
return -1;
}
void solve(){
per(i,1,n/2){//n为偶数和奇数都是用的情况
per(j,1,n/2){
int num = get_num(4);
if(num == -1){
printf("NO\n");
return ;
}
a[i][j] = a[n+1-i][j] = a[i][n+1-j] = a[n+1-i][n+1-j] = num;
}
}
if(n & 1){//奇数要处理中间行和列
per(i,1,n/2){
int num = get_num(2);
if(num == -1){
printf("NO\n");
return ;
}
a[i][(n+1)/2] = a[n+1-i][(n+1)/2] = num;
num = get_num(2);
if(num == -1){
printf("NO\n");
return ;
}
a[(n+1)/2][i] = a[(n+1)/2][n+1-i] = num;
}
int num = get_num(1);
if(num == -1){
printf("NO\n");
return ;
}
a[(n+1)/2][(n+1)/2] = num;
}
printf("YES\n");
per(i,1,n){
per(j,1,n){
printf("%d%c",a[i][j],j == n ? '\n' : ' ');
}
}
}
int main(){
while(~scanf("%d",&n)){
mp.clear();
per(i,1,n*n){
int x = 0;
scanf("%d",&x);
++mp[x];
}
solve();
}
return 0;
}
垃圾AC代码(没有归纳好):
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
typedef long long LL;
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define mem(a,b) memset(a,b,sizeof(a))
#define per(i,a,b) for(int i = a;i <= b;++i)
#define rep(i,a,b) for(int i = a;i >= b;--i)
const int maxn = 1e3;
int n = 0,m = 0;
//int times[maxn+10];
map<int,int> mp;
int b[maxn+10];
int a[30][30];
void solve(){
map<int,int>::iterator it = mp.begin();
int num[maxn+10];
int cnt = 0;
if(n % 2 == 0){
for(it = it;it != mp.end();++it){
per(i,1,it->second / 4){
num[++cnt] = it->first;
}
}
int p = 0;
per(i,1,n/2){
per(j,1,n/2){
a[i][j] = num[++p];
}
}
per(i,1,n/2){
per(j,n/2+1,n){
a[i][j] = a[i][n+1-j];
}
}
per(i,n/2+1,n){
per(j,1,n){
a[i][j] = a[n+1-i][j];
}
}
}else{
int center = 0;
int np2[maxn+10];
int cnt = 0,cnt2 = 0;
for(it = mp.begin();it != mp.end();++it){
if(it->second & 1){
center = it->first;
it->second -= 1;
}
if(it->second >= 4){
per(i,1,it->second/4){
num[++cnt] = it->first;
}
}
if(it->second % 4 == 2 && it->second != 0){//不可能只有1这一个小于4的数
np2[++cnt2] = it->first;
}
}
//cout << "na " <<cnt <<" " <<cnt2 << endl;
if(cnt2 > n-1 && n != 1){
printf("NO\n");
return ;
}
int mid = (n+1)/2;
a[mid][mid] = center;
int pos = 1;
bool flag = false;
per(i,1,cnt2){
a[pos][mid] = a[n+1-pos][mid] = np2[i];
++pos;
if(pos == mid){
flag = true;
break;
}
}
bool flag2 = false;
int k = 1;
if(flag == true){
pos = 1;
per(i,n/2+1,cnt2){
a[mid][pos] = a[mid][n+1-pos] = np2[i];
++pos;
if(pos == mid){
flag2 = true;
break;
}
}
int ps = 0;
if(flag2 == false){
//cout << "hah" << endl;
for(k = 1;k <= cnt;){
//cout << "nihao " << k << " " <<pos << endl;
a[mid][pos] = a[mid][n+1-pos] = num[k];
++pos;++ps;
if(ps % 2 == 0){
++k;
}
if(pos == mid){
break;
}
a[mid][pos] = a[mid][n+1-pos] = num[k];
++pos;++ps;
if(ps % 2 == 0){
++k;
}
if(pos == mid){
break;
}
}
}
// cout << "nima " <<k << " " <<cnt << endl;
}else{
//cout << "po " << pos <<" " <<k << " " <<cnt << " " << cnt2 <<endl;
int ps = 0;
//cout << "niam " << pos << "" << k << endl;
for(k = 1;k <= cnt;){
// cout << pos <<" ji " << num[k] << endl;
a[pos][mid] = a[n+1-pos][mid] = num[k];
++pos;++ps;
if(ps % 2 == 0){
++k;
}
if(pos == mid){
break;
}
a[pos][mid] = a[n+1-pos][mid] = num[k];
++pos;++ps;
if(ps % 2 == 0){
++k;
}
if(pos == mid){
break;
}
}
pos = 1;
for(k = k;k <= cnt;){
a[mid][pos] = a[mid][n+1-pos] = num[k];
++pos;++ps;
if(ps % 2 == 0){
++k;
}
if(pos == mid){
break;
}
a[mid][pos] = a[mid][n+1-pos] = num[k];
++pos;++ps;
if(ps % 2 == 0){
++k;
}
if(pos == mid){
break;
}
}
}
int p = k;
per(i,1,n/2){
per(j,1,n/2){
//if(i == n/2){
// cout <<"ko " << p <<" " << num[p] << endl;
//}
a[i][j] = num[p++];
}
}
per(i,1,n/2){
per(j,n/2+1,n){
a[i][j] = a[i][n+1-j];
}
}
per(i,n/2+1,n){
per(j,1,n){
a[i][j] = a[n+1-i][j];
}
}
}
printf("YES\n");
per(i,1,n){
per(j,1,n){
printf("%d%c",a[i][j],j == n ? '\n': ' ');
}
}
}
int main(){
while(~scanf("%d",&n)){
mp.clear();
per(i,1,n*n){
scanf("%d",&b[i]);
++mp[b[i]];
}
map<int,int>::iterator it = mp.begin();
if(n % 2 == 0){
for(it = it;it != mp.end();++it){
if(it->second % 4 != 0){
printf("NO\n");
return 0;
}
}
}else{
int flag = 0;
for(it = mp.begin();it != mp.end();++it){
if(it->second & 1){
++flag;
if(flag > 1){
printf("NO\n");
return 0;
}
}
}
}
solve();
}
return 0;
}