先给出BFS的思路吧,大概都是这样做的
struct node
{
int x, y, step;
};//根据需要定义结构体
int vis[MAX][MAX]={0};//二维三维之类的看题目给的条件
queue q;
q.push(start);//把起点压入队列
node pre,nex;
vis[start.x][start.y]=1;//一般是设置为1,如果有其他需要可以更改
while(!q.empty()){
pre = q.front();
if(xxx) break; //xxx是终点的判断
q.pop();
for(int i=0;i<4;i++){//i不一定是小于4,看题目来定
if(xxxx){//如果满足怎样的条件将这种情况压入队列
q.push(xx);
vis[xx.x][xx.y]=1;//别忘了标记来过
}
}
}
if(!q.empty()){
//就是找到了终点
}
else{
//没有找到终点
}
A friend of you is doing research on the Traveling Knight Problem (TKP) where you are to find the shortest closed tour of knight moves that visits each square of a given set of n squares on a chessboard exactly once. He thinks that the most difficult part of the problem is determining the smallest number of knight moves between two given squares and that, once you have accomplished this, finding the tour would be easy.
Of course you know that it is vice versa. So you offer him to write a program that solves the "difficult" part.
Your job is to write a program that takes two squares a and b as input and then determines the number of knight moves on a shortest route from a to b.
The input file will contain one or more test cases. Each test case consists of one line containing two squares separated by one space. A square is a string consisting of a letter (a-h) representing the column and a digit (1-8) representing the row on the chessboard.
For each test case, print one line saying "To get from xx to yy takes n knight moves.".
题意:马步踏棋,日字走法,问你几步能到达终点。所以方向有八个!!!
#include
#include
using namespace std;
struct node
{char x;
int y,step;};
int main(){
char x1,x2;
int y1,y2;
queue q;
node start,temp;
while(~scanf("%c%d %c%d",&x1,&y1,&x2,&y2)){
getchar();
int vis[150][9]={0};
for(int i=0;i<150;i++)
for(int j=0;j<9;j++)
vis[i][j]=0;
while(!q.empty())//清空
q.pop();
start.x=x1;start.y=y1;start.step=0;
q.push(start);
vis[start.x][start.y]=1;
while(!q.empty()){
start = q.front();
if(start.x==x2&&start.y==y2)break;
q.pop();
//2,1
temp.x=start.x+2;temp.y=start.y+1;
if(temp.x<='h'&&temp.y<=8&&vis[temp.x][temp.y]!=1){
temp.step=start.step+1;
q.push(temp);
vis[temp.x][temp.y]=1;
}
//2,-1
temp.x=start.x+2;temp.y=start.y-1;
if(temp.x<='h'&&temp.y>0&&vis[temp.x][temp.y]!=1){
temp.step=start.step+1;
q.push(temp);
vis[temp.x][temp.y]=1;
}
//-2,1
temp.x=start.x-2;temp.y=start.y+1;
if(temp.x>='a'&&temp.y<=8&&vis[temp.x][temp.y]!=1){
temp.step=start.step+1;
q.push(temp);
vis[temp.x][temp.y]=1;
}
//-2,-1
temp.x=start.x-2;temp.y=start.y-1;
if(temp.x>='a'&&temp.y>=1&&vis[temp.x][temp.y]!=1){
temp.step=start.step+1;
q.push(temp);
vis[temp.x][temp.y]=1;
}
//1,2
temp.x=start.x+1;temp.y=start.y+2;
if(temp.x<='h'&&temp.y<=8&&vis[temp.x][temp.y]!=1){
temp.step=start.step+1;
q.push(temp);
vis[temp.x][temp.y]=1;
}
//1,-2
temp.x=start.x+1;temp.y=start.y-2;
if(temp.x<='h'&&temp.y>0&&vis[temp.x][temp.y]!=1){
temp.step=start.step+1;
q.push(temp);
vis[temp.x][temp.y]=1;
}
//-1,2
temp.x=start.x-1;temp.y=start.y+2;
if(temp.x>='a'&&temp.y<=8&&vis[temp.x][temp.y]!=1){
temp.step=start.step+1;
q.push(temp);
vis[temp.x][temp.y]=1;
}
//-1,-2
temp.x=start.x-1;temp.y=start.y-2;
if(temp.x>='a'&&temp.y>=1&&vis[temp.x][temp.y]!=1){
temp.step=start.step+1;
q.push(temp);
vis[temp.x][temp.y]=1;
}
}
printf("To get from %c%d to %c%d takes %d knight moves.\n",x1,y1,x2,y2,q.front().step);
}
}
当时没有用一个数组把8种情况存下来,所以造成代码量比较多。。。
然后就是另一种BFS了(基础类型的变形)
题意:有一个特别的电梯,第i层有一个对应的数字ki, 对于第i层按上升键up可升上到i+k[i]层,按下降键down到达i-k[i]层,到达的楼层最高不能超过n层,最低不能小于1层。给你一个起点A和终点B,问最少要按几次上升键或者下降键到达目的地。
思路:多用一个数组记录每一层楼能咋走,其实就是用这个把For循环的那部分代替了,就是这部分创新,其实自己思考下也能做出来的
#include
using namespace std;
struct node
{int lou,step;};
int main(){
int a,b,c;
queue q;
node start,temp;
while(scanf("%d",&a)&&a!=0){
scanf("%d %d",&b,&c);
int floor[200]={0},vis[200]={0};
for(int i=1;i <= a;i++){
scanf("%d",&floor[i]);
vis[i]=0;
}
while(!q.empty())//清空
q.pop();
start.lou=b;start.step=0;
q.push(start);
vis[start.lou]=1;
while(!q.empty()){
start = q.front();
if(start.lou==c)break;
q.pop();
temp.lou=start.lou+floor[start.lou];
if(temp.lou<=a&&vis[temp.lou]!=1){
temp.step=start.step+1;
q.push(temp);
vis[temp.lou]=1;
}
temp.lou=start.lou-floor[start.lou];
if(temp.lou>0&&vis[temp.lou]!=1){
temp.step=start.step+1;
q.push(temp);
vis[temp.lou]=1;
}
}
if(q.empty()) printf("-1\n");
else printf("%d\n",q.front().step);
}
}
#include
using namespace std;
struct node
{int x,y,wan,fangxiang;};
int vis[101][101];
int main(){
int x1,x2,y1,y2,k;
int a,b,c;
queue q;
node start,temp;
scanf("%d",&a);
while(a--){
char map[101][101]={'\0'};
scanf("%d %d",&b,&c);
for(int i=0;i=temp.wan)&&temp.x=temp.wan)&&temp.y=0&&(vis[temp.x][temp.y]==0||vis[temp.x][temp.y]>=temp.wan)&&map[temp.x][temp.y]=='.'&&start.wan<=k+1){
//printf("down\n");
if(start.fangxiang==3){
temp.fangxiang=3;
temp.wan=start.wan;
}
else{
temp.fangxiang=3;
temp.wan=start.wan+1;
}
vis[temp.x][temp.y]=temp.wan;
//printf("turn:%d\n",temp.wan);
q.push(temp);
}
//向左
temp.x=start.x;temp.y=start.y-1;
if(start.fangxiang==4)temp.wan=start.wan;
else temp.wan=start.wan+1;
if(temp.y>=0&&(vis[temp.x][temp.y]==0||vis[temp.x][temp.y]>=temp.wan)&&map[temp.x][temp.y]=='.'&&start.wan<=k+1){
//printf("left\n");
if(start.fangxiang==4){
temp.fangxiang=4;
temp.wan=start.wan;
}
else{
temp.fangxiang=4;
temp.wan=start.wan+1;
}
vis[temp.x][temp.y]=temp.wan;
q.push(temp);
}
}
if(q.empty()){
printf("no\n");
}
else
printf("yes\n");
}
}
现在来解释为啥需要这么做,这其实因为先左再下与先下再左步数虽然一致,但是从(0,0)到(1,1)之后,(1,1)的方向可不一样,下一次向下或者向左很影响转弯数的增减,所以要标记
题解:给你一个图,图上的标志如题所述,碰到怪兽就一定要把它杀死,求花时间最少的最短路径。
这个题贼好,真的贼好,有很多新颖的点,这个也要赋予VIS数组实际意义,详细的贴完代码说
#include
using namespace std;
struct node
{int x,y,time;};
int vis[120][120];
int a,b;
int turn[4][2]={0,1,1,0,0,-1,-1,0};
node start,temp;
bool check(int x,int y,int z){
if(x>=0&&y>=0&&xz))
return true;
return false;
}
int main(){
node roate[120][120];
int i;
while(~scanf("%d %d",&a,&b)){
memset(roate,0,sizeof(roate));
char Map[120][120]={'\0'};
memset(Map,0,sizeof(Map));
memset(vis,0,sizeof(vis));
for(i=0;i q;
while(!q.empty())
q.pop();
start.x=0;
start.y=0;
start.time=0;
q.push(start);
while(!q.empty()){
start=q.front();
q.pop();
for(i=0;i<4;i++){
temp.x=turn[i][0]+start.x;
temp.y=turn[i][1]+start.y;
if(Map[temp.x][temp.y]=='.')
temp.time=start.time+1;
if(Map[temp.x][temp.y]<='9'&&Map[temp.x][temp.y]>='1')
temp.time=start.time+Map[temp.x][temp.y]-'0'+1;
if(Map[temp.x][temp.y]=='.'&&check(temp.x,temp.y,temp.time)){
vis[temp.x][temp.y]=temp.time;
q.push(temp);
roate[temp.x][temp.y]=start;
}
if(Map[temp.x][temp.y]<='9'&&Map[temp.x][temp.y]>='1'&&check(temp.x,temp.y,temp.time)){
vis[temp.x][temp.y]=temp.time;
q.push(temp);
roate[temp.x][temp.y]=start;
}
}
}
if(vis[a-1][b-1]==0)
printf("God please help our poor hero.\n");
else{
printf("It takes %d seconds to reach the target position, let me show you the way.\n",vis[a-1][b-1]);
stackv;
while(!v.empty())
v.pop();
start.x=a-1;start.y=b-1;start.time=vis[a-1][b-1];
while(!(start.x==0&&start.y==0)){
v.push(start);
start = roate[start.x][start.y];
}
start.x=0,start.y=0,start.time=0;
v.push(start);int flag=1;
while(!(v.top().x==a-1&&v.top().y==b-1)){
int time1=v.top().time;
printf("%ds:(%d,%d)->",flag,v.top().x,v.top().y);
v.pop();
printf("(%d,%d)\n",v.top().x,v.top().y);
flag++;
int lzk=0;
while(v.top().time-time1-lzk!=1){
printf("%ds:FIGHT AT (%d,%d)\n",flag,v.top().x,v.top().y);
flag++;lzk++;
}
}
}printf("FINISH\n");
}
}
这个题喃,要把VIS赋值当前所花的时间,为啥要这么做呢,与前面那个题可不一样,这个题其实与BFS利用队列的原理有关系,本来是到时候通过Front()获取的元素就应该是最早的到达终点的情况,可是打怪就破坏了这个,在没有打怪的情况下不论怎么走每次都是走1s,但是打怪会走多于1s,就破坏了队列自己带来的优势,所以没有用优先队列的情况下,就要赋予VIS实际意义,每一次走过这个点就要判断是否走过,如果走过花费的时间是不是最少,不是就更新这个情况,所以呢,需要把队列所有都跑完直到队列变空,大概思想就是这样,还有一点最重要的,就是记录路径,这个也很复杂,我是用一个二维数组记录的,然后遇到一个问题,这个是倒着的,我们需要倒序输出,这里用了STL的Stack,利用了栈的先进先出。
又是一个类型的题
剩下有空再写