-
题意: "车"只能走直线,"后"可以走直线和斜线,它们每一步只能走到能走到的位置中没走过的数字最小的位置。如果能走到的位置都走了,但棋盘还有不能直接走到的位置,可以花费1van去跳转到当前棋盘中未走的数字最小的位置。现在让你构造这个N x N的棋盘,使"车"的花费小于"后"。
-
题解: 这题想不出来做法,看题解后豁然开朗。如果直接去构造我们好像只有3x3的还可以手动构造。如果3x3的构造知道。我们可以在n*n(n>3)的棋盘中把之前构造的3x3的棋盘放在左上角,然后在其他位置从第n行第n列向左上角蛇形从1构造,假设除左上角3x3的位置外总共构造num个值,那左上角3x3的格子加上num.
-
相当于从最外面"引" "后"和"车"走到左上角3x3的格子里,外面是蛇形构造的所以它们花费都是0,但在最开始构造的3x3格子中,"后"比"车"多花费1van。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<queue>
#include<vector>
#include<string>
#include<fstream>
using namespace std;
#define rep(i, a, n) for(int i = a; i <= n; ++ i);
#define per(i, a, n) for(int i = n; i >= a; -- i);
typedef long long ll;
const int N = 5e2 + 105;
const int mod = 998244353;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f;
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
//
int n;
int res[N][N];
int main()
{
scanf("%d",&n);
if(n < 3){
printf("-1\n");
return 0;
}
res[1][1] = 4, res[1][2] = 5, res[1][3] = 9;
res[2][1] = 3, res[2][2] = 2, res[2][3] = 6;
res[3][1] = 1, res[3][2] = 8, res[3][3] = 7;
int top = n, num = 0;
while(top > 3){
if(top % 2 == 0){
for(int i = 1; i <= top; ++ i) res[i][top] = ++ num;
for(int i = top - 1; i >= 1; -- i) res[top][i] = ++ num;
}
else{
for(int i = 1; i <= top; ++ i) res[top][i] = ++ num;
for(int i = top - 1; i >= 1; -- i) res[i][top] = ++ num;
}
top --;
}
for(int i = 1; i <= n; ++ i){
for(int j = 1; j <= n; ++ j){
if(i <= 3 && j <= 3) res[i][j] += num;
if(j == 1) printf("%d",res[i][j]);
else printf(" %d",res[i][j]);
}
printf("\n");
}
return 0;
}