题意:一个n*n格的棋盘,从1标号到n*n。从1开始走,每次投色子,可走1到6步中的任意一个步数,问最少投几次色子可到最后一格。其中有两种特殊通道,蛇和梯子,在蛇头所在的格子可以直接走到蛇尾所在的格子,在梯子底端所在的格子可以直接走到梯子顶端所在的格子。
思路:由于蛇和梯子作用是一样的,所以可以把它们看成一种。又由于蛇和梯子是不会重合的,所以它们不可能在同一个位置出现。故可以用bar[x]数组来保存在特殊位置x处可以到达的位置y。棋盘用mp数组表示,1表示能到达,0表示不能到达。
#include<iostream> #include<string.h> #include<stdio.h> #include<queue> using namespace std; const int N=23; struct node { int from,to; }; int main() { int t,n,s,l; int mp[N*N],mp1[N*N];//棋盘 node bar[250];//梯子和蛇 scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&s,&l); for(int i=1;i<=s+l;i++) { scanf("%d%d",&bar[i].from,&bar[i].to); } memset(mp,0,sizeof(mp)); mp[1]=1;//从第一格开始,初始化为1; int step=0,deal;//step初始化筛子次数 while(mp[n*n]==0)//终点为1即为到达终点 { memcpy(mp1,mp,sizeof(mp));//mp1【】备份上一步的棋盘状态 memset(mp,0,sizeof(mp));//mp【】保存上一步棋盘状态下进行拓展后的状态 for(int j=1;j<=n*n-1;j++) { if(mp1[j]==0) continue;//上一步无法到达此格,则跳过 for(int i=1;i<=6;i++)//筛子点数1到6,走后到达j+i位置; { deal=0; if(j+i>n*n) break;//超出棋盘,break; for(int k=1;k<=s+l;k++) { if(bar[k].from==j+i)//如果j+i位置是蛇或是梯子,到达他的to位置 { mp[bar[k].to]=1; deal=1;break; } } if(!deal&&!mp[j+i]) mp[j+i]=1;//不利用蛇或者梯子 } } step++;//摇骰子次数加一 } printf("%d ",step); } return 0; } /* 2 6 1 3 35 25 3 23 5 16 20 33 */