CF1065D Three Pieces

本文探讨了一道复杂的搜索题,目标是在一个n*n的棋盘上寻找从起点到终点的最短路径,同时考虑最少的棋子类型转换次数。棋盘上的每个格子都有特定的值,且棋子可以在车、马、相三种类型间转换,每转换一次增加额外的时间成本。文章通过详细的代码和算法解析,展示了如何高效地解决这一问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:给出一个n*n的棋盘,棋盘上每个格子有一个值。你有一个子,要求将这个子从1移到n*n(去k时可以经过比k大的点)。

开局时它可以作为车,马,相(国际象棋)。每走一步耗费时间1。你也可以中途将它换为车,马,相(国际象棋),耗费时间1。

求最短时间,以及保证最短时间的最少替换次数。

题解:

一道恶心人的搜索题。对于每个点分为n*n*3种状态,表示当前已经经过1 ~ k,当前是车 / 马 / 相。

对于每个状态讨论做车 / 马 / 相怎么走,以及将它换成另外两种的情况。

代码(已经不想再写一遍了):

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 15
int n,mp[N][N],rx,ry,lx,ly;
int dis[N][N][N*N][3],f[N][N][N*N][3];
bool vis[N][N][N*N][3];
struct node
{
    int x,y,d,typ;
    node(){}
    node(int x,int y,int d,int typ):x(x),y(y),d(d),typ(typ){}
}tp;
queue<node>q;
int dx[8]={-2,-2,-1,-1,1,1,2,2};
int dy[8]={-1,1,-2,2,-2,2,-1,1};
void ins(int x,int y,int d,int t)
{
    if(!vis[x][y][d][t])
    {
        vis[x][y][d][t]=1;
        q.push(node(x,y,d,t));
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            scanf("%d",&mp[i][j]);
            if(mp[i][j]==1)
            {
                rx=i,ry=j;
            }else if(mp[i][j]==n*n)
            {
                lx=i,ly=j;
            }
        }
    }
    memset(dis,0x3f,sizeof dis);
    memset(f,0x3f,sizeof f);
    dis[rx][ry][1][0]=dis[rx][ry][1][1]=dis[rx][ry][1][2]=0;
    f[rx][ry][1][0]=f[rx][ry][1][1]=f[rx][ry][1][2]=0;
    q.push(node(rx,ry,1,0));q.push(node(rx,ry,1,1));q.push(node(rx,ry,1,2));
    vis[rx][ry][1][0]=vis[rx][ry][1][1]=vis[rx][ry][1][2]=1;
    int x,y,d,t,tx,ty,dd;
    while(!q.empty())
    {
        tp=q.front();
        q.pop();
        x=tp.x,y=tp.y,d=tp.d,t=tp.typ;
        vis[x][y][d][t]=0;
        if(t==0)
        {
            for(int i=0;i<n;i++)
            {
                dd = d+(mp[i][y]==d+1);
                if(dis[i][y][dd][t]>dis[x][y][d][t]+1)
                {
                    dis[i][y][dd][t]=dis[x][y][d][t]+1;
                    f[i][y][dd][t]=f[x][y][d][t];
                    ins(i,y,dd,t);
                }else if(dis[i][y][dd][t]==dis[x][y][d][t]+1)
                {
                    if(f[i][y][dd][t]>f[x][y][d][t])
                    {
                        f[i][y][dd][t]=f[x][y][d][t];
                        ins(i,y,dd,t);
                    }
                }
                dd = d+(mp[x][i]==d+1);
                if(dis[x][i][dd][t]>dis[x][y][d][t]+1)
                {
                    dis[x][i][dd][t]=dis[x][y][d][t]+1;
                    f[x][i][dd][t]=f[x][y][d][t];
                    ins(x,i,dd,t);
                }else if(dis[x][i][dd][t]==dis[x][y][d][t]+1)
                {
                    if(f[x][i][dd][t]>f[x][y][d][t])
                    {
                        f[x][i][dd][t]=f[x][y][d][t];
                        ins(x,i,dd,t);
                    }
                }
            }
            if(dis[x][y][d][1]>dis[x][y][d][0]+1)
            {
                dis[x][y][d][1]=dis[x][y][d][0]+1;
                f[x][y][d][1]=f[x][y][d][0]+1;
                ins(x,y,d,1);
            }else if(dis[x][y][d][1]==dis[x][y][d][0]+1)
            {
                if(f[x][y][d][1]>f[x][y][d][0]+1)
                {
                    f[x][y][d][1]=f[x][y][d][0]+1;
                    ins(x,y,d,1);
                }
            }
            if(dis[x][y][d][2]>dis[x][y][d][0]+1)
            {
                dis[x][y][d][2]=dis[x][y][d][0]+1;
                f[x][y][d][2]=f[x][y][d][0]+1;
                ins(x,y,d,2);
            }else if(dis[x][y][d][2]==dis[x][y][d][0]+1)
            {
                if(f[x][y][d][2]>f[x][y][d][0]+1)
                {
                    f[x][y][d][2]=f[x][y][d][0]+1;
                    ins(x,y,d,2);
                }
            }
        }else if(t==1)
        {
            for(int i=0;i<8;i++)
            {
                tx = x+dx[i],ty = y+dy[i];
                if(tx<0||ty<0||tx>=n||ty>=n)continue;
                dd = d+(mp[tx][ty]==d+1);
                if(dis[tx][ty][dd][t]>dis[x][y][d][t]+1)
                {
                    dis[tx][ty][dd][t]=dis[x][y][d][t]+1;
                    f[tx][ty][dd][t]=f[x][y][d][t];
                    ins(tx,ty,dd,t);
                }else if(dis[tx][ty][dd][t]==dis[x][y][d][t]+1)
                {
                    if(f[tx][ty][dd][t]>f[x][y][d][t])
                    {
                        f[tx][ty][dd][t]=f[x][y][d][t];
                        ins(tx,ty,dd,t);
                    }
                }
            }
            if(dis[x][y][d][0]>dis[x][y][d][1]+1)
            {
                dis[x][y][d][0]=dis[x][y][d][1]+1;
                f[x][y][d][0]=f[x][y][d][1]+1;
                ins(x,y,d,0);
            }else if(dis[x][y][d][0]==dis[x][y][d][1]+1)
            {
                if(f[x][y][d][0]>f[x][y][d][1]+1)
                {
                    f[x][y][d][0]=f[x][y][d][1]+1;
                    ins(x,y,d,0);
                }
            }
            if(dis[x][y][d][2]>dis[x][y][d][1]+1)
            {
                dis[x][y][d][2]=dis[x][y][d][1]+1;
                f[x][y][d][2]=f[x][y][d][1]+1;
                ins(x,y,d,2);
            }else if(dis[x][y][d][2]==dis[x][y][d][1]+1)
            {
                if(f[x][y][d][2]>f[x][y][d][1]+1)
                {
                    f[x][y][d][2]=f[x][y][d][1]+1;
                    ins(x,y,d,2);
                }
            }
        }else
        {
            for(int i=1;x-i>=0&&y-i>=0;i++)
            {
                tx = x-i,ty = y-i;
                dd = d+(mp[tx][ty]==d+1);
                if(dis[tx][ty][dd][t]>dis[x][y][d][t]+1)
                {
                    dis[tx][ty][dd][t]=dis[x][y][d][t]+1;
                    f[tx][ty][dd][t]=f[x][y][d][t];
                    ins(tx,ty,dd,t);
                }else if(dis[tx][ty][dd][t]==dis[x][y][d][t]+1)
                {
                    if(f[tx][ty][dd][t]>f[x][y][d][t])
                    {
                        f[tx][ty][dd][t]=f[x][y][d][t];
                        ins(tx,ty,dd,t);
                    }
                }
            }
            for(int i=1;x+i<n&&y-i>=0;i++)
            {
                tx = x+i,ty = y-i;
                dd = d+(mp[tx][ty]==d+1);
                if(dis[tx][ty][dd][t]>dis[x][y][d][t]+1)
                {
                    dis[tx][ty][dd][t]=dis[x][y][d][t]+1;
                    f[tx][ty][dd][t]=f[x][y][d][t];
                    ins(tx,ty,dd,t);
                }else if(dis[tx][ty][dd][t]==dis[x][y][d][t]+1)
                {
                    if(f[tx][ty][dd][t]>f[x][y][d][t])
                    {
                        f[tx][ty][dd][t]=f[x][y][d][t];
                        ins(tx,ty,dd,t);
                    }
                }
            }
            for(int i=1;x-i>=0&&y+i<n;i++)
            {
                tx = x-i,ty = y+i;
                dd = d+(mp[tx][ty]==d+1);
                if(dis[tx][ty][dd][t]>dis[x][y][d][t]+1)
                {
                    dis[tx][ty][dd][t]=dis[x][y][d][t]+1;
                    f[tx][ty][dd][t]=f[x][y][d][t];
                    ins(tx,ty,dd,t);
                }else if(dis[tx][ty][dd][t]==dis[x][y][d][t]+1)
                {
                    if(f[tx][ty][dd][t]>f[x][y][d][t])
                    {
                        f[tx][ty][dd][t]=f[x][y][d][t];
                        ins(tx,ty,dd,t);
                    }
                }
            }
            for(int i=1;x+i<n&&y+i<n;i++)
            {
                tx = x+i,ty = y+i;
                dd = d+(mp[tx][ty]==d+1);
                if(dis[tx][ty][dd][t]>dis[x][y][d][t]+1)
                {
                    dis[tx][ty][dd][t]=dis[x][y][d][t]+1;
                    f[tx][ty][dd][t]=f[x][y][d][t];
                    ins(tx,ty,dd,t);
                }else if(dis[tx][ty][dd][t]==dis[x][y][d][t]+1)
                {
                    if(f[tx][ty][dd][t]>f[x][y][d][t])
                    {
                        f[tx][ty][dd][t]=f[x][y][d][t];
                        ins(tx,ty,dd,t);
                    }
                }
            }
            if(dis[x][y][d][0]>dis[x][y][d][2]+1)
            {
                dis[x][y][d][0]=dis[x][y][d][2]+1;
                f[x][y][d][0]=f[x][y][d][2]+1;
                ins(x,y,d,0);
            }else if(dis[x][y][d][0]==dis[x][y][d][2]+1)
            {
                if(f[x][y][d][0]>f[x][y][d][2]+1)
                {
                    f[x][y][d][0]=f[x][y][d][2]+1;
                    ins(x,y,d,0);
                }
            }
            if(dis[x][y][d][1]>dis[x][y][d][2]+1)
            {
                dis[x][y][d][1]=dis[x][y][d][2]+1;
                f[x][y][d][1]=f[x][y][d][2]+1;
                ins(x,y,d,1);
            }else if(dis[x][y][d][1]==dis[x][y][d][2]+1)
            {
                if(f[x][y][d][1]>f[x][y][d][2]+1)
                {
                    f[x][y][d][1]=f[x][y][d][2]+1;
                    ins(x,y,d,1);
                }
            }
        }
    }
    int ans = dis[lx][ly][n*n][0],tk=f[lx][ly][n*n][0];
    if(dis[lx][ly][n*n][1]<ans)
    {
        ans=dis[lx][ly][n*n][1];
        tk =f[lx][ly][n*n][1];
    }else if(dis[lx][ly][n*n][1]==ans)
    {
        tk=min(tk,f[lx][ly][n*n][1]);
    }
    if(dis[lx][ly][n*n][2]<ans)
    {
        ans=dis[lx][ly][n*n][2];
        tk =f[lx][ly][n*n][2];
    }else if(dis[lx][ly][n*n][2]==ans)
    {
        tk=min(tk,f[lx][ly][n*n][2]);
    }
    printf("%d %d\n",ans,tk);
    return 0;
}

 

转载于:https://www.cnblogs.com/LiGuanlin1124/p/9880864.html

能否帮我对答案的统计进行完善并给出解释```#include<bits/stdc++.h> using namespace std; const int MAXN = 15; int N, ans1 = 0x3f3f3f3f, ans2 = 0x3f3f3f3f; int a[MAXN][MAXN], now[MAXN][5], dist[MAXN][MAXN], ans[MAXN][5]; int head[MAXN], cnt; struct star{ int nxt, to, w; }edge[MAXN * 4]; void add( int u, int v, int w ){ // cout << u << " " << v << " " << w - 10000 << endl; dist[u][v] = w; dist[v][u] = w; // edge[++ cnt] = { head[u], v, w }; // head[u] = cnt; } //================star_edge int fx1[] = { 2, 1, -2, -1 }; int fy1[] = { 1, 2, -1, -2 }; bool vis[MAXN][MAXN]; void rook(){ for( int i = 1; i <= N; i ++ ){ for( int j = 1; j <= N; j ++ ){ for( int k = 1; k <= N; k ++ ){ add( a[i][j], a[i][k], 10000 ); add( a[i][k], a[i][j], 10000 ); add( a[i][j], a[k][j], 10000 ); add( a[k][j], a[i][j], 10000 ); } } } } void knight( int x, int y, int cnt ){ if( cnt >= N * N ) return ; vis[x][y] = true; for( int i = 0; i < 4; i ++ ){ int nx = fx1[i] + x; int ny = fy1[i] + y; if( nx >= 1 && ny >= 1 && nx <= N && ny <= N && !vis[nx][ny] ){ vis[nx][ny] = true; add( a[x][y] + N * N, a[nx][ny] + N * N, 10000 ); add( a[nx][ny] + N * N, a[x][y] + N * N, 10000 ); knight( nx, ny, cnt + 1 ); vis[nx][ny] = false; } } } void bishop(){ for( int i = 1; i <= N; i ++ ){ for( int j = 1; j <= N; j ++ ){ for( int k = 1; k <= N; k ++ ){ int t = i + j - k; if( t <= 0 || t > N ) continue; add( a[i][j] + N * N * 2, a[k][t] + N * N * 2, 10000 ); add( a[k][t] + N * N * 2, a[i][j] + N * N * 2, 10000 ); } } } } void hebing(){ for( int i = 1; i <= N; i ++ ){ add( i, i + N * N, 10001 ); add( i + N * N, i, 10001 ); add( i, i + N * N * 2, 10001 ); add( i + N * N * 2, i, 10001 ); add( i + N * N, i + N * N * 2, 10001 ); add( i + N * N * 2, i + N * N, 10001 ); } } //================add_edge void floyd(){ for( int k = 1; k <= N; k ++ ){ for( int i = 1; i <= N; i ++ ){ for( int j = 1; j <= N; j ++ ){ dist[i][j] = min( dist[i][j], dist[i][k] + dist[k][j] ); } } } } int main(){ cin >> N; memset( dist, 0x3f, sizeof( dist ) ); for( int i = 1; i <= N; i ++ ){ for( int j = 1; j <= N; j ++ ){ cin >> a[i][j]; now[a[i][j]][1] = i; now[a[i][j]][2] = j; } } rook(); knight( 1, 1, 1 ); bishop(); hebing(); floyd(); for( int i = 1; i <= N * N; i ++ ){ // int x = now[i][1], y = now[i][2]; // cout << dist[x][y] / 10000 << " " << dist[x][y] % 10000 << endl; // ans1 += dist[x][y] / 10000; // ans2 += ans2, dist[x][y] % 10000; } cout << ans1 << " " << ans2; return 0; }```不要改变变量名、思路和算法,不要使用复杂的变量名,迫不得已使用简短的变量名来创建变量,顺便看看前面的代码有没有问题,如有问题,请修改并且标记出,不要改变原来的结构 题面如下# CF1065D Three Pieces ## 题目描述 你遇到了一种新型的国际象棋谜题。你得到的棋盘不一定是 $8 \times 8$,但它仍然是 $N \times N$ 的。每个格子上都写有一个数字,所有数字都是从 $1$ 到 $N^2$,且两两不同。第 $i$ 行第 $j$ 列的格子上写着数字 $A_{ij}$。 你的棋子只有三种:马、象和车。开始时,你可以任选一种棋子放在数字为 $1$ 的格子上。然后你需要依次到达数字为 $2$ 的格子(过程中可以经过其他格子),再到数字为 $3$ 的格子,依此类推,直到到达数字为 $N^2$ 的格子。每一步你可以选择用当前棋子进行一次合法移动,或者将当前棋子更换为另一种棋子。每个格子可以被多次经过。 马可以移动到横向两格纵向一格,或纵向两格横向一格的格子。象可以沿对角线移动。车可以沿横向或纵向移动。每次移动都必须到达当前格子不同的格子。 你希望使整个遍历过程的步数最少。在所有步数相同的方案中,你还希望棋子更换次数最少。 你应该采取怎样的路径以满足所有条件? ## 输入格式 第一行包含一个整数 $N$($3 \le N \le 10$),表示棋盘的大小。 接下来的 $N$ 行,每行包含 $N$ 个整数 $A_{i1}, A_{i2}, \dots, A_{iN}$($1 \le A_{ij} \le N^2$),表示棋盘上每个格子上的数字。 保证所有 $A_{ij}$ 两两不同。 ## 输出格式 输出一行,包含两个整数,分别表示最优方案的步数和更换棋子的次数。 ## 输入输出样例 #1 ### 输入 #1 ``` 3 1 9 3 8 6 7 4 2 5 ``` ### 输出 #1 ``` 12 1 ``` ## 说明/提示 以下是第一个样例的步骤(起始棋子为马): 1. 移动到 $(3, 2)$ 2. 移动到 $(1, 3)$ 3. 移动到 $(3, 2)$ 4. 更换马为车 5. 移动到 $(3, 1)$ 6. 移动到 $(3, 3)$ 7. 移动到 $(3, 2)$ 8. 移动到 $(2, 2)$ 9. 移动到 $(2, 3)$ 10. 移动到 $(2, 1)$ 11. 移动到 $(1, 1)$ 12. 移动到 $(1, 2)$ 由 ChatGPT 4.1 翻译
07-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值