Codeforces Round #632 (Div. 2) E.Road to 1600(思維題/構造 遞歸)

題目

給你一個數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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章