题解:CF1065D Three Pieces

题目传送门

思路:

拆点跑最短路。

\(n^2\) 个点拆成 \(3n^2\) 个,对应马,象和车三种状态。

不同状态之间连一条 \(1\) 的边,相同的连 \(0\),连边按照三种棋的走法连即可。

对于要依次遍历 \(1,2,3,...,n^2\) 的限制,我们可以先以 \(1\) 的三种状态为起点跑最短路,接着以 \(2\) 的三种状态跑最短路,以此类推,到以 \(n^2-1\) 的三种状态为起点跑最短路,即可得出最终到 \(n^2\) 的最短路、

注意每次换起点跑最短路,除起点外上一次最短路的状态都要清除。

复杂度为 \(O(n^4\log n)\)

const int N=11,inf=1e9;
int id[N][N],val[N*N],n;
vector<pair<int,int>>G[N*N*3];
int ds[N*N*3],dc[N*N*3];
bool vis[N*N*3];
int dx[8]={-2,-2,-1,-1,1,1,2,2},dy[8]={-1,1,-2,2,-2,2,-1,1};
void Dijistra(int St)
{
    for(int i=1;i<=n*n;i++)
    {
        if(St==i) continue;
        else for(int j=1;j<=3;j++)
            ds[(i-1)*3+j]=dc[(i-1)*3+j]=inf;
    }
    memset(vis,0,sizeof(vis));
    priority_queue<pair<int,int>>q;
    q.push({-ds[(St-1)*3+1],(St-1)*3+1});
    q.push({-ds[(St-1)*3+2],(St-1)*3+2});
    q.push({-ds[(St-1)*3+3],(St-1)*3+3});
    while(q.size())
    {
        auto [D,now]=q.top();q.pop();
	    if(vis[now]) continue;
        vis[now]=1;
        for(auto [to,val]:G[now])
        {
            if(ds[to]>ds[now]+1+val){
                ds[to]=ds[now]+1+val,dc[to]=dc[now]+val;
                q.push({-ds[to],to});
            }
            else if(ds[to]==ds[now]+1+val){
                if(dc[to]>dc[now]+val){
                    dc[to]=dc[now]+val,q.push({-ds[to],to});
                }
            }
        }
    }
    return;
}
int main()
{
    fin>>n;
    for(int i=1,x;i<=n;i++)
        for(int j=1;j<=n;j++) 
            fin>>x,val[x]=(id[i][j]=(i-1)*n+j);
    for(int i=1,x,y;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            x=id[i][j];
            for(int p=1;p<=3;p++)
                for(int q=1;q<=3;q++)
                {
                    if(q==1){
                        for(int k=0;k<8;k++)
                        {
                            int nx=i+dx[k],ny=j+dy[k];
                            if(nx<1||ny<1||nx>n||ny>n) continue;
                            y=id[nx][ny];
                            G[(x-1)*3+p].push_back({(y-1)*3+q,p!=q});
                        }
                    }
                    if(q==2){
                        for(int nx=i-1,ny=j-1;nx&&ny;nx--,ny--)
                            y=id[nx][ny],G[(x-1)*3+p].push_back({(y-1)*3+q,p!=q});
                        for(int nx=i-1,ny=j+1;nx&&ny<=n;nx--,ny++)
                            y=id[nx][ny],G[(x-1)*3+p].push_back({(y-1)*3+q,p!=q});
                        for(int nx=i+1,ny=j-1;nx<=n&&ny;nx++,ny--)
                            y=id[nx][ny],G[(x-1)*3+p].push_back({(y-1)*3+q,p!=q});
                        for(int nx=i+1,ny=j+1;nx<=n&&ny<=n;nx++,ny++)
                            y=id[nx][ny],G[(x-1)*3+p].push_back({(y-1)*3+q,p!=q});
                    }
                    if(q==3){
                        for(int nx=i,ny=j+1;ny<=n;ny++)
                             y=id[nx][ny],G[(x-1)*3+p].push_back({(y-1)*3+q,p!=q});
                        for(int nx=i,ny=j-1;ny;ny--)
                             y=id[nx][ny],G[(x-1)*3+p].push_back({(y-1)*3+q,p!=q});
                        for(int nx=i-1,ny=j;nx;nx--)
                             y=id[nx][ny],G[(x-1)*3+p].push_back({(y-1)*3+q,p!=q});
                        for(int nx=i+1,ny=j;nx<=n;nx++)
                             y=id[nx][ny],G[(x-1)*3+p].push_back({(y-1)*3+q,p!=q});
                    }
                }
        }
    for(int i=1;i<n*n;i++) Dijistra(val[i]);
    pair<int,int>x={ds[(val[n*n]-1)*3+1],dc[(val[n*n]-1)*3+1]};
    pair<int,int>y={ds[(val[n*n]-1)*3+2],dc[(val[n*n]-1)*3+2]};
    pair<int,int>z={ds[(val[n*n]-1)*3+3],dc[(val[n*n]-1)*3+3]};
    pair<int,int>Ans=min({x,y,z});
    fout<<Ans.first<<' '<<Ans.second;
    return 0;
}
posted @ 2024-11-11 17:30  EityDawn  阅读(45)  评论(0)    收藏  举报