题目描述:给出一个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 ",ans,tk); return 0; }