这题真的快搞死我了
首先一遍读入一遍桶排序
要是偶数的情况的话,则右上角1/4那块应该与左上角1/4那块对称,然后上半部分和下半部分对称
所以,每个数的数量都要是4的倍数,判断可行性
然后填充,填充只用填充右上角1/4,对称得到左上角1/4,再对称得到下半部分
现在考虑奇数的情况
设mid = n / 2 + 1,要是忽略mid行和mid列,则剩下的区域和偶数部分是一样的处理
但是现在要注意!
mid列只需以中心为mid,mid的那个点对称,mid行也是,而mid行和mid列没有关系!!!
此处提供一组数据:
7 5 9 5 4 1 9 8 4 5 1 4 10 7 7 8 4 2 4 4 5 4 4 10 3 4 6 8 1 9 9 5 6 8 7 1 8 6 6 7 5 3 1 1 4 7 2 3 3 8
那么奇数的情况就是先填充除了mid行和mid列的,然后判断这些填充区域是否存在0,若存在则不可行
然后判断剩下的桶是否 非2的倍数的数只有1个,否则,不可行
然后填充mid行和mid列就ok
我代码的话奇数部分和偶数部分其实有很多相同之处(事实上我是复制再修改的),所以如果参考的话可以先看偶数部分再看奇数部分
#include<bits/stdc++.h>
using namespace std;
int tong[1010];
int mp[30][30];
int main()
{
int n;
scanf("%d", &n);
for(int i = 1; i <= n * n; i ++)
{
int temp;
scanf("%d", &temp);
tong[temp] ++;
}
if(n % 2 == 0)
{
int flag = 1;
for(int i = 1; i <= 1000; i ++)
{
if(tong[i] % 4 != 0)
{
flag = 0;
break;
}
}
if(!flag)
{
printf("NO\n");
return 0;
}
int mid = n / 2;
int now = 1;
for(int i = 1; i <= 1000; i ++)
{
while(tong[i])
{
int x = (now - 1) / mid + 1, y = now - (x - 1) * mid;
mp[x][y] = i;
//cout << x << " " << y << " " << i << endl;
tong[i] -= 4;
now ++;
}
}
for(int i = 1; i <= mid; i ++)
{
for(int j = 1; j <= mid; j ++)
{
mp[i][n + 1 - j] = mp[i][j];
}
}
for(int i = 1; i <= mid; i ++)
{
for(int j = 1; j <= n; j ++)
{
mp[n + 1 - i][j] = mp[i][j];
}
}
}
else
{
int mid = n / 2;
int now = 1;
for(int i = 1; i <= 1000; i ++)
{
while(tong[i] >= 4)
{
int x = (now - 1) / mid + 1, y = now - (x - 1) * mid;
mp[x][y] = i;
//cout << x << " " << y << " " << i << endl;
tong[i] -= 4;
now ++;
if(now > mid * mid)
break;
}
if(now > mid * mid)
break;
}
int flag = 1, num = 0;
for(int i = 1; i <= 1000; i ++)
{
if(tong[i] % 2 != 0)
{
if(tong[i] % 2 == 1 && num == 0)
num = 1;
else
{
flag = 0;
break;
}
}
}
for(int i = 1; i <= mid; i ++)
for(int j = 1; j <= mid; j ++)
if(mp[i][j] == 0)
{
flag = 0;
break;
}
if(!flag)
{
printf("NO\n");
return 0;
}
now = 1;
for(int i = 1; i <= 1000; i ++)
{
while(tong[i] >= 2)
{
mp[now][mid + 1] = i;
tong[i] -= 2;
now ++;
if(now > mid)
break;
}
if(now > mid)
break;
}
now = 1;
for(int i = 1; i <= 1000; i ++)
{
while(tong[i] >= 2)
{
mp[mid + 1][now] = i;
tong[i] -= 2;
now ++;
if(now > mid)
break;
}
if(now > mid)
break;
}
for(int i = 1; i <= mid; i ++)
{
mp[mid + 1][n - i + 1] = mp[mid + 1][i];
}
for(int i = 1; i <= 1000; i ++)
{
if(tong[i])
{
mp[mid + 1][mid + 1] = i;
break;
}
}
for(int i = 1; i <= mid; i ++)
{
for(int j = 1; j <= mid; j ++)
{
mp[i][n + 1 - j] = mp[i][j];
}
}
for(int i = 1; i <= mid; i ++)
{
for(int j = 1; j <= n; j ++)
{
mp[n + 1 - i][j] = mp[i][j];
}
}
}
printf("YES\n");
for(int i = 1; i <= n; i ++)
{
for(int j = 1; j <= n; j ++)
printf("%d ", mp[i][j]);
printf("\n");
}
return 0;
}