1. 程式人生 > >PAT 乙級 1050 螺旋矩陣

PAT 乙級 1050 螺旋矩陣

1050 螺旋矩陣 (25 point(s))

本題要求將給定的 N 個正整數按非遞增的順序,填入“螺旋矩陣”。所謂“螺旋矩陣”,是指從左上角第 1 個格子開始,按順時針螺旋方向填充。要求矩陣的規模為 m 行 n 列,滿足條件:m×n 等於 N;m≥n;且 m−n 取所有可能值中的最小值。

輸入格式:

輸入在第 1 行中給出一個正整數 N,第 2 行給出 N 個待填充的正整數。所有數字不超過 10​4​​,相鄰數字以空格分隔。

輸出格式:

輸出螺旋矩陣。每行 n 個數字,共 m 行。相鄰數字以 1 個空格分隔,行末不得有多餘空格。

輸入樣例:

12
37 76 20 98 76 42 53 95 60 81 58 93

輸出樣例:

98 95 93
42 37 81
53 20 76
58 60 76

經驗總結:

emmmmmm 怎麼說呢,這一題其實思路上還是有點難度的,不知道怎麼控制輸出,實際上解決方法是按照順序控制下標一點點的填滿二維陣列,最後再按照二維陣列的規律輸出,詳細程式碼就在下面,這裡說一點,書上的程式碼提交後,最後一個測試點會超時(或者出錯?),我的解決方法是,對於所有的10^4以下的質數進行特判,因為質數N肯定是N行1列,如果用傳統的思路可能就會超時,特判的方式當然就是利用質數表啦~(๑•̀ㅂ•́)و✧

AC程式碼 

#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=10010;
int a[maxn],b[maxn][maxn];
bool flag[maxn]={false};
bool cmp(int a,int b)
{
	return a>b;
}
void find_prime()
{
	for(int i=2;i<maxn;++i)
	{
		if(flag[i]==false)
		{
			for(int j=i+i;j<maxn;j+=i)
			{
				flag[j]=true;
			}
		}
	}
}
void print(int row,int col)
{
	for(int i=1;i<=row;++i)
	{
		for(int j=1;j<=col;++j)
		{				
			printf("%d",b[i][j]);
			if(j!=col)
				printf(" ");
			else
				printf("\n");
		}
	}
}
int main()
{
	int n;
	find_prime();
	while(~scanf("%d",&n))
	{
		for(int i=0;i<n;++i)
			scanf("%d",&a[i]);
		if(n==1)
		{
			printf("%d",a[0]);
		}
		else if(flag[n]==false)
		{
			sort(a,a+n,cmp);
			for(int i=0;i<n;++i)
				printf("%d\n",a[i]);
		}
		else
		{

			sort(a,a+n,cmp);
			int row=(int)ceil(sqrt(1.0*n));
			while(n%row!=0)
				++row;
			int col=n/row;
			int U=1,D=row,L=1,R=col;
			int i=1,j=1,num=0;
			while(num<n)
			{
				while(j<R&&num<n)
				{
					b[i][j]=a[num++];
					++j;
				}
				while(i<D&&num<n)
				{
					b[i][j]=a[num++];
					++i;
				}
				while(j>L&&num<n)
				{
					b[i][j]=a[num++];
					--j;
				}
				while(i>U&&num<n)
				{
					b[i][j]=a[num++];
					--i;
				}
				++U,--R,--D,++L;
				++j;++i;
				if(num==n-1)
				{
					b[i][j]=a[num++];
				}
			}
			print(row,col);
		}
	}
	return 0;
}