DFS(深搜),注意优化一下剪枝和求最小未使用数这两部分的代码就行了。
#include<iostream>
using namespace std;
int PrimeList[50];
int board[100];
int NumUsed[101],MinNum;
int size;
void Solve();
int Acceptable(int k,int cur);
int IsPrime(int k);
int main()
{
int data,i,j,k,flag;
cin>>data;
PrimeList[0] = 2;
PrimeList[1] = k = 3;
for(i=2;i<50;i++)
{
flag = 0;
while(!flag)
{
k += 2;
flag = 1;
for(j=1;j<i;j++)
{
if(k % PrimeList[j] == 0)
{
flag = 0;
break;
}
}
}
PrimeList[i] = k;
}//Generate a prime list
while(data-- > 0)
{
cin>>size;
Solve();
}
return 0;
}
void Solve()
{
int i,j,k,flag,cur = 0;
for(i=0;i<100;i++) board[i] = NumUsed[i] = 0;
MinNum = flag = 1;
while(cur < size*size)
{
if(board[0] >= size*size)
{
flag = 0;
break;
}
if(0 == board[cur])
{
k = MinNum;
if(((cur/size + cur%size) % 2) ^ (k%2 == 0)) k++;
}
else
k = board[cur] + 2;
while(k <= size*size && !Acceptable(k,cur)) k += 2;
if(k <= size*size)
{
board[cur++] = k;
NumUsed[k] = 1;
if(MinNum == k)
while(NumUsed[++MinNum]);
}
else
{
board[cur] = 0;
k = board[--cur];
NumUsed[k] = 0;
if(MinNum > k) MinNum = k;
}
}
if(flag)
{
for(i=0;i<size;i++)
{
cout<<board[i*size];
for(j=1;j<size;j++)
cout<<' '<<board[i*size+j];
cout<<endl;
}
}
else
cout<<"NO\n";//Print results
}
int Acceptable(int k,int cur)
{
if(NumUsed[k]) return 0;
int a = cur%size,b = cur/size,flag = 1;
if(a > 0) flag = (flag && IsPrime(k + board[cur-1]));
if(b > 0) flag = (flag && IsPrime(k + board[cur-size]));
return flag;
}
int IsPrime(int k)
{
int Min = 0,Max = 49,Mid;
while(Min < Max)
{
Mid = (Min + Max) / 2;
if(PrimeList[Mid] > k) Max = Mid - 1;
else if(PrimeList[Mid] < k) Min = Mid + 1;
else return 1;
}
return PrimeList[Min] == k;
}
using namespace std;
int PrimeList[50];
int board[100];
int NumUsed[101],MinNum;
int size;
void Solve();
int Acceptable(int k,int cur);
int IsPrime(int k);
int main()
{
int data,i,j,k,flag;
cin>>data;
PrimeList[0] = 2;
PrimeList[1] = k = 3;
for(i=2;i<50;i++)
{
flag = 0;
while(!flag)
{
k += 2;
flag = 1;
for(j=1;j<i;j++)
{
if(k % PrimeList[j] == 0)
{
flag = 0;
break;
}
}
}
PrimeList[i] = k;
}//Generate a prime list
while(data-- > 0)
{
cin>>size;
Solve();
}
return 0;
}
void Solve()
{
int i,j,k,flag,cur = 0;
for(i=0;i<100;i++) board[i] = NumUsed[i] = 0;
MinNum = flag = 1;
while(cur < size*size)
{
if(board[0] >= size*size)
{
flag = 0;
break;
}
if(0 == board[cur])
{
k = MinNum;
if(((cur/size + cur%size) % 2) ^ (k%2 == 0)) k++;
}
else
k = board[cur] + 2;
while(k <= size*size && !Acceptable(k,cur)) k += 2;
if(k <= size*size)
{
board[cur++] = k;
NumUsed[k] = 1;
if(MinNum == k)
while(NumUsed[++MinNum]);
}
else
{
board[cur] = 0;
k = board[--cur];
NumUsed[k] = 0;
if(MinNum > k) MinNum = k;
}
}
if(flag)
{
for(i=0;i<size;i++)
{
cout<<board[i*size];
for(j=1;j<size;j++)
cout<<' '<<board[i*size+j];
cout<<endl;
}
}
else
cout<<"NO\n";//Print results
}
int Acceptable(int k,int cur)
{
if(NumUsed[k]) return 0;
int a = cur%size,b = cur/size,flag = 1;
if(a > 0) flag = (flag && IsPrime(k + board[cur-1]));
if(b > 0) flag = (flag && IsPrime(k + board[cur-size]));
return flag;
}
int IsPrime(int k)
{
int Min = 0,Max = 49,Mid;
while(Min < Max)
{
Mid = (Min + Max) / 2;
if(PrimeList[Mid] > k) Max = Mid - 1;
else if(PrimeList[Mid] < k) Min = Mid + 1;
else return 1;
}
return PrimeList[Min] == k;
}