有一个 的矩阵每次可以往上右移动一格

你还可以最多进行一次跳跃如果并且那么可以从跳跃到

求出最小的操作次数并给出一种方案

首先如果我们不使用跳跃那么直接即可。

分别表示到起点终点的距离如果没有路径则其值为

如果进行跳跃设我从跳到那么这种方案的

那么我们需要对于每个能走到的点进行一次矩阵查询最小值

可以使用单调队列来解决具体方法是先在轴上做一遍滑动窗口再把求出的答案在轴上再做一遍滑动窗口

然而我赛时写的是一个

来优化查询复杂度下界是具体效率看数据强度和剪枝强度

目前经过多次调参和加火车头只能通过的数据

有没有人写个kdtree暴力过去啊,标算太trival了,没意思

解法

//96.67%
#include <bits/stdc++.h>
#pragma GCC optimize(3)
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
using namespace std;
template <typename T> void read(T &x){
    static char ch; x = 0,ch = getchar();
    while (!isdigit(ch)) ch = getchar();
    while (isdigit(ch)) x = x * 10 + ch - '0',ch = getchar();
}
inline int Get(){
    static char ch; ch = getchar();
    while (ch!='.'&&ch!='X'&&ch!='S'&&ch!='T')ch=getchar();
    return ch;
}
inline void write(int x){if (x > 9) write(x/10); putchar(x%10+'0'); }
const int N = 2005,V = 2005 * 2005,INF = 5000 * 5000 + 5;
int n,m,K; char mp[N][N];
inline bool in(int x,int y){ return 0<=x&&x<n&&0<=y&&y<m; } 
struct Point{
    int x,y;
    bool in(){ return 0<=x&&x<n&&0<=y&&y<m; } 
    Point(int xx=0,int yy=0){ x=xx,y=yy; }
}s,t,ps[V],pt[V]; int ls,lt;
Point Q[V]; int ql,qr;
const int txy[] = {1,0,-1,0,1};
int dis[N][N],dit[N][N]; Point lss[N][N],lst[N][N];
inline void Bfs1(){
    register int i,j; Point A,B;
    Q[ql=qr=1] = ps[ls=1] = s; dis[s.x][s.y] = 1;
    while (ql <= qr){
        A = Q[ql],++ql;
        for (i = 0; i < 4; ++i){
            B = A,B.x += txy[i],B.y += txy[i+1];
            if (B.in() && !dis[B.x][B.y] && mp[B.x][B.y] != 'X'){
                dis[B.x][B.y] = dis[A.x][A.y] + 1,lss[B.x][B.y] = A;
                Q[++qr] = B,ps[++ls] = B;
            }
        }
    }
    Q[ql=qr=1] = pt[lt=1] = t; dit[t.x][t.y] = 1;
    while (ql <= qr){
        A = Q[ql],++ql;
        for (i = 0; i < 4; ++i){
            B = A,B.x += txy[i],B.y += txy[i+1];
            if (B.in() && !dit[B.x][B.y] && mp[B.x][B.y] != 'X'){
                dit[B.x][B.y] = dit[A.x][A.y] + 1,lst[B.x][B.y] = A;
                Q[++qr] = B,pt[++lt] = B; 
            }
        }
    }
    for (i = 0; i < n; ++i) for (j = 0; j < m; ++j){
        if (!dis[i][j]) dis[i][j] = INF;
        if (!dit[i][j]) dit[i][j] = INF;
    }
}
inline bool cmpx(Point A,Point B){ return A.x < B.x; }
inline bool cmpy(Point A,Point B){ return A.y < B.y; }
inline bool cmpd(Point A,Point B){ return dit[A.x][A.y] <= dit[B.x][B.y]; }
inline Point Mn(Point A,Point B){ return cmpd(A,B) ? A : B; }
Point A[V],P[V];
int lc[V],rc[V],mxx[V],mxy[V],mnx[V],mny[V],cnto; Point mnd[V];
int Build(int l,int r,int d){
    if (l > r) return 0;
    int o = ++cnto,mid = l + r >> 1;
    if (d) nth_element(A+l,A+mid,A+r+1,cmpy); else nth_element(A+l,A+mid,A+r+1,cmpx);
    mnd[o] = P[o] = A[mid];
    mxx[o] = mnx[o] = A[mid].x;
    mxy[o] = mny[o] = A[mid].y;
    if (lc[o] = Build(l,mid-1,d^1)){
        mxx[o] = max(mxx[o],mxx[lc[o]]),mxy[o] = max(mxy[o],mxy[lc[o]]);
        mnx[o] = min(mnx[o],mnx[lc[o]]),mny[o] = min(mny[o],mny[lc[o]]);
        mnd[o] = Mn(mnd[o],mnd[lc[o]]);
    }
    if (rc[o] = Build(mid+1,r,d^1)){
        mxx[o] = max(mxx[o],mxx[rc[o]]),mxy[o] = max(mxy[o],mxy[rc[o]]);
        mnx[o] = min(mnx[o],mnx[rc[o]]),mny[o] = min(mny[o],mny[rc[o]]);
        mnd[o] = Mn(mnd[o],mnd[rc[o]]);
    }
    return o;
}
int ans; Point qans,anss,anst;
int qxl,qxr,qyl,qyr,vvv;
inline void Ask(int o){
    if (cmpd(qans,mnd[o]) || dit[mnd[o].x][mnd[o].y] + vvv >= ans || qxr < mnx[o] || qxl > mxx[o] || qyl > mxy[o] || qyr < mny[o]) return;
    if (qxl <= mnx[o] && mxx[o] <= qxr && qyl <= mny[o] && mxy[o] <= qyr){
        qans = Mn(qans,mnd[o]); return;
    }
    if (qxl <= P[o].x && P[o].x <= qxr && P[o].y >= qyl && P[o].y <= qyr) qans = Mn(qans,P[o]);
    if (lc[o]) Ask(lc[o]); if (rc[o]) Ask(rc[o]);
}
Point Ans[V]; int la;
inline void Print(){
    write(la-1),putchar('\n');
    for (register int i = 1; i <= la; ++i) write(Ans[i].x),putchar(' '),write(Ans[i].y),putchar('\n');
}
inline void Getans1(){
    Point A;
    if (dis[t.x][t.y] >= INF){ puts("-1"); return; }
    Ans[la=1] = s;
    while (Ans[la].x != t.x || Ans[la].y != t.y) Ans[la+1] = lst[Ans[la].x][Ans[la].y],++la;
    Print();
}
#define MOD 32
#define W 1
#define LIMIT 10000
#define LIMIT2 100000
inline void solve2(){
    register int i,j,v;
    swap(lt,ls); swap(pt,ps); swap(s,t);
    for (i = 0; i < n; ++i) for (j = 0; j < m; ++j)
        swap(dis[i][j],dit[i][j]),swap(lss[i][j],lst[i][j]);
    ans = INF,anss = anst = Point(-1,-1);
    for (i = 1; i <= lt; ++i) A[i] = pt[i];
    Build(1,lt,1);
//    random_shuffle(ps+1,ps+ls+1);
    int TOT = 0;
    for (i = 1; i <= ls; ++i) if (ls<=LIMIT||i%MOD<=W){
        qxl = ps[i].x - K,qxr = ps[i].x + K;
        qyl = ps[i].y - K,qyr = ps[i].y + K;
        qxl = max(qxl,0),qyl = max(qyl,0),qxr = min(qxr,n-1),qyr = min(qyr,m-1);
        vvv = dis[ps[i].x][ps[i].y] + 1,qans = ps[i],Ask(1);
        v = dit[qans.x][qans.y] + dis[ps[i].x][ps[i].y] + 1;
        if (v < ans) ans = v,anss = ps[i],anst = qans;
        ++TOT;
        if (TOT>=LIMIT2&&ans>=INF){
            puts("-1"); return;
        }
    }
    if (ans >= INF){ puts("-1"); return;  }
    Ans[la=1] = anss;
    while (Ans[la].x != s.x || Ans[la].y != s.y) Ans[1+la] = lss[Ans[la].x][Ans[la].y],++la;
    reverse(Ans+1,Ans+la+1); Ans[++la] = anst;
    while (Ans[la].x != t.x || Ans[la].y != t.y) Ans[1+la] = lst[Ans[la].x][Ans[la].y],++la;
    reverse(Ans+1,Ans+la+1);
    Print();
}

int main(){
    register int i,j,v; //srand(time(NULL));
    read(n),read(m),read(K);
    for (i = 0; i < n; ++i) for (j = 0; j < m; ++j) mp[i][j] = Get();
    for (i = 0; i < n; ++i) for (j = 0; j < m; ++j)
        if (mp[i][j] == 'S') s = Point(i,j); else if (mp[i][j] == 'T') t = Point(i,j);
    Bfs1();
    if (!K){ Getans1(); return 0; }
    bool flag = 0;
    if (lt < ls){
        solve2(); return 0;
    }
    ans = INF,anss = anst = Point(-1,-1);
    for (i = 1; i <= lt; ++i) A[i] = pt[i];
    Build(1,lt,1);
//    random_shuffle(ps+1,ps+ls+1);
    int TOT = 0;
    for (i = 1; i <= ls; ++i) if (ls<=LIMIT||i%MOD<=W){
        qxl = ps[i].x - K,qxr = ps[i].x + K;
        qyl = ps[i].y - K,qyr = ps[i].y + K;
        qxl = max(qxl,0),qyl = max(qyl,0),qxr = min(qxr,n-1),qyr = min(qyr,m-1);
        vvv = dis[ps[i].x][ps[i].y] + 1,qans = ps[i],Ask(1);
        v = dit[qans.x][qans.y] + dis[ps[i].x][ps[i].y] + 1;
        if (v < ans) ans = v,anss = ps[i],anst = qans;
        ++TOT;
        if (TOT>=LIMIT2&&ans>=INF){
            puts("-1"); return 0;
        }
    }
    if (ans >= INF){ puts("-1"); return 0;  }
    Ans[la=1] = anss;
    while (Ans[la].x != s.x || Ans[la].y != s.y) Ans[1+la] = lss[Ans[la].x][Ans[la].y],++la;
    reverse(Ans+1,Ans+la+1); Ans[++la] = anst;
    while (Ans[la].x != t.x || Ans[la].y != t.y) Ans[1+la] = lst[Ans[la].x][Ans[la].y],++la;
    Print();
    return 0;
}