题目
给你一个数n(n<=500),代表你需要构造一个n*n的矩阵,
该矩阵中,每个格子放上[1,n²]中的一个数,且每个数只能出现一次
把国际象棋中的车和皇后初始放在数字1所在的格子,
对于车(可横竖走)和皇后(可横竖斜走)来说,它们会按照以下的方案走:
①如果在车/皇后一步可达的范围内,存在没有走过的格子,就去这些格子中数值最小的那个格子
②如果不存在,就传送到数值最小的格子,并产生1 vun的费用
然后继续①操作,直至走完所有格子
你需要构造一个n*n的矩阵,
使得车产生的费用严格小于皇后产生的费用,输出矩阵
思路来源
Roundgod代码
题解
n=1和n=2显然无解,因为皇后根本不会产生费用
题目给了一个4*4的样例,考虑到可以把4*4的值升到[n*n-15,n*n],
并从4*4的入口进入最后的4*4矩阵,n>4就可以做了
然而发现可以手玩一个3*3的矩阵,并把1固定在左上角,把3*3的矩阵固定在整个矩阵的右上角
递归求n-1,分奇偶,依次在外层添一道弧,
保证最终能进入原3*3的矩阵入口即可
代码
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define sci(a) scanf("%d",&(a))
#define pb push_back
#define SZ(x) (int)(x.size())
const int N=510;
typedef vector<int> vec;
typedef vector<vec> mat;
mat a(3,vec(3));
int n;
mat dfs(int n){
if(n==3){
return a;
}
mat b=dfs(n-1),c(n,vec(n));
//让b矩阵当c矩阵的右上角 且保持值最大
rep(i,0,n-2){
rep(j,1,n-1){
c[i][j]=b[i][j-1]+2*n-1;
}
}
int t=0;
if(n%2==0){
per(i,n-1,0){
c[n-1][i]=++t;
}
per(i,n-2,0){
c[i][0]=++t;
}
}
else{
rep(i,0,n-1){
c[i][0]=++t;
}
rep(i,1,n-1){
c[n-1][i]=++t;
}
}
return c;
}
int main(){
a[0][0]=1;a[0][1]=4;a[0][2]=5;
a[1][0]=7;a[1][1]=6;a[1][2]=9;
a[2][0]=8;a[2][1]=3;a[2][2]=2;
sci(n);
if(n<3){
puts("-1");
}
else{
mat ans=dfs(n);
rep(i,0,n-1){
rep(j,0,n-1){
printf("%d%c",ans[i][j]," \n"[j==n-1]);
}
}
}
return 0;
}