初学算法----广度优先搜索--关于记录最优路径的问题

迷宫问题

描述:

定义一个二维数组:

int maze[5][5] = {

0, 1, 0, 0, 0,

0, 1, 0, 1, 0,

0, 0, 0, 0, 0,

0, 1, 1, 1, 0,

0, 0, 0, 1, 0,

};


它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

 

输入:

一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。

输出:

左上角到右下角的最短路径,格式如样例所示。

样例输入:

0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

样例输出:

(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)
像这种问题因为要记录最优路径,所以在一个点访问完后,并且拓展出其周围全部的点后,并不能就丢弃,而是应该储存起来;
然后通过下标,回溯寻找出路径,有一种链表的感觉;
如下是AC代码:
 1 #include<bits/stdc++.h>
 2 #include<cstring>
 3 using namespace std;
 4 struct STR{
 5     int y;
 6     int x;
 7     int fathersub;//通过记录拓展出自己的下标和自己的下标,到最后找到了路径能够遍历打印出
 8     int selfsub;
 9 }mapway[50];
10 int maper[6][6];
11 int vis[6][6];
12 int dy[]={-1,0,1,0},dx[]={0,1,0,-1};
13 int main()
14 {
15     memset(vis,0,sizeof (vis));
16     for (int i=0;i<5;i++)
17     {
18         for (int j=0;j<5;j++)
19         {
20             cin>>maper[i][j];
21         }
22     }
23     vis[0][0]=1;
24     int waysub=0,tracesub=1;
25     ++waysub;
26     mapway[waysub].y=0;
27     mapway[waysub].x=0;
28     mapway[waysub].fathersub=-1;
29     mapway[waysub].selfsub=waysub;
30     while (1)
31     {
32         if (mapway[tracesub].y==4 && mapway[tracesub].x==4)
33         {
34             break;
35         }
36         else
37         {
38             for (int i=0;i<4;i++)
39             {
40                 int nexty=mapway[tracesub].y+dy[i];
41                 int nextx=mapway[tracesub].x+dx[i];
42                 if (nexty<0 || nextx<0 || nexty>4 || nextx>4 || maper[nexty][nextx]==1 || vis[nexty][nextx]==1)
43                 {
44                     continue;
45                 }
46                 else
47                 {
48                     ++waysub;
49                     mapway[waysub].y=nexty;
50                     mapway[waysub].x=nextx;
51                     mapway[waysub].fathersub=mapway[tracesub].selfsub;
52                     mapway[waysub].selfsub=waysub;
53                     vis[nexty][nextx]=1; //千万不要忘记这一步,我写的时候总是忘记导致调试时,很费时间;
54                 }
55             }
56         }
57         tracesub++;
58     }
59 //因为是从最初点到最后点的路径,所以要反一下;
60     int gathersub[50]={0};
61     int waynum=0;
62     int resub=mapway[tracesub].fathersub;
63     gathersub[++waynum]=mapway[tracesub].selfsub;
64     while (1)
65     {
66         if (resub==-1)
67         {
68             break;
69         }
70         gathersub[++waynum]=resub;
71         resub=mapway[resub].fathersub;
72     }
73     reverse(gathersub+1,gathersub+waynum+1);
74     for (int i=1;i<=waynum;i++)
75     {
76         cout<<"("<<mapway[gathersub[i]].y<<","<<" "<<mapway[gathersub[i]].x<<")";
77         if (i!=waynum)
78         {
79             cout<<endl;
80         }
81     }
82     return 0;
83 }
会发现如这段代码很费地方,而且写起来很麻烦,可以有如下优化:
mapway[waysub].y=0;
mapway[waysub].x=0;
mapway[waysub].fathersub=-1; mapway[waysub].selfsub=waysub;

struct STR{
    int y;
    int x;
    int fathersub;
    int selfsub;
    STR (int yy,int xx,int fsub,int ssub):y(yy),x(xx),fathersub(fsub),selfsub(ssub){}
    STR (){}
};

然后每一次就可以这么写:

 mapway[++waysub]=STR(1,1,-1,waysub);

这是c++的内容:解释一下就是

STR (int yy,int xx,int fsub,int ssub):y(yy),x(xx),fathersub(fsub),selfsub(ssub){}
STR (){}
相当于:
STR (int yy,int xx,int fsub,int ssub){
int y=yy;
int x=xx;
int fathersub=fsub;
int selfsub=ssub;
}
 隐含的路径广度优先搜索:

Pots


描述:

You are given two pots, having the volume of A and B liters respectively. The following operations can be performed:

  1. FILL(i)        fill the pot i (1 ≤ i ≤ 2) from the tap;
  2. DROP(i)      empty the pot i to the drain;
  3. POUR(i,j)    pour from pot i to pot j; after this operation either the pot j is full (and there may be some water left in the pot i), or the pot i is empty (and all its contents have been moved to the pot j).

Write a program to find the shortest possible sequence of these operations that will yield exactly C liters of water in one of the pots.

输入:

On the first and only line are the numbers A, B, and C. These are all integers in the range from 1 to 100 and C≤max(A,B).

输出:

The first line of the output must contain the length of the sequence of operations K. The following K lines must each describe one operation. If there are several sequences of minimal length, output any one of them. If the desired result can’t be achieved, the first and only line of the file must contain the word ‘impossible’.

样例输入:

3 5 4

样例输出:

6
FILL(2)
POUR(2,1)
DROP(1)
POUR(2,1)
FILL(2)
POUR(2,1)
将两个pot中水的状态看做条件,要达到其中一个水的容积为c,因为有6个操作,所以可以遍历这6个操作,看一下到所有水的状态都被遍历后是否能够找到:
非常的见鬼,我怎么写总是错误,只好给出大佬的代码:https://blog.csdn.net/qq_43588832/article/details/86534717
  1 #include<bits/stdc++.h>
  2 #include<string>
  3 using namespace std;
  4 struct STR{
  5     int sita;
  6     int sitb;
  7     int waynum;
  8     int fathersub;
  9     int selfsub;
 10     STR (int a,int b,int num,int fsub,int ssub):
 11     sita(a),sitb(b),waynum(num),fathersub(fsub),selfsub(ssub){}
 12     STR (){}
 13 };
 14 STR wayer[10005];
 15 int headsub=1,tailsub=0;
 16 string wayname[7]={
 17     "blank","FILL(1)","POUR(1,2)","DROP(1)","FILL(2)","POUR(2,1)","DROP(2)"
 18 };
 19 int vis[105][105];
 20 int main()
 21 {
 22     int a,b,c;
 23     cin>>a>>b>>c;
 24     memset(vis,0,sizeof (vis));
 25     wayer[++tailsub]=STR(0,0,0,0,tailsub);
 26     vis[0][0]=1;
 27     while (1)
 28     {
 29         if (headsub==tailsub+1 || (wayer[headsub].sita==c || wayer[headsub].sitb==c))
 30         {
 31             break;
 32         }
 33         else
 34         {
 35             //1
 36             if (vis[a][wayer[headsub].sitb]==0)
 37             {
 38                 wayer[++tailsub]=STR(a,wayer[headsub].sitb,1,headsub,tailsub);
 39                 vis[a][wayer[headsub].sitb]=1;
 40             }
 41             //2
 42             if (wayer[headsub].sita+wayer[headsub].sitb>b)
 43             {
 44                 if (vis[wayer[headsub].sita+wayer[headsub].sitb-b][b]==0)
 45                 {
 46                     wayer[++tailsub]=STR(wayer[headsub].sita+wayer[headsub].sitb-b,b,2,headsub,tailsub);
 47                     vis[wayer[headsub].sita+wayer[headsub].sitb-b][b]=1;
 48                 }
 49             }
 50             else if (wayer[headsub].sita+wayer[headsub].sitb<=b)
 51             {
 52                 if (vis[0][wayer[headsub].sita+wayer[headsub].sitb]==0)
 53                 {
 54                     wayer[++tailsub]=STR(0,wayer[headsub].sita+wayer[headsub].sitb,2,headsub,tailsub);
 55                     vis[0][wayer[headsub].sita+wayer[headsub].sitb]=1;
 56                 }
 57             }
 58             //3
 59             if (vis[0][wayer[headsub].sitb]==0)
 60             {
 61                 wayer[++tailsub]=STR(0,wayer[headsub].sitb,3,headsub,tailsub);
 62                 vis[0][wayer[headsub].sitb]=1;
 63             }
 64             //4
 65             if (vis[wayer[headsub].sita][b]==0)
 66             {
 67                 wayer[++tailsub]=STR(wayer[headsub].sita,b,4,headsub,tailsub);
 68             }
 69             //5
 70             if (wayer[headsub].sita+wayer[headsub].sitb>a)
 71             {
 72                 if (vis[a][wayer[headsub].sita+wayer[headsub].sitb-a]==0)
 73                 {
 74                     wayer[++tailsub]=STR(a,wayer[headsub].sita+wayer[headsub].sitb-a,5,headsub,tailsub);
 75                     vis[a][wayer[headsub].sita+wayer[headsub].sitb-a]=1;
 76                 }
 77             }
 78             else if (wayer[headsub].sita+wayer[headsub].sitb<=a)
 79             {
 80                 if (vis[wayer[headsub].sita+wayer[headsub].sitb][0]==0)
 81                 {
 82                     wayer[++tailsub]=STR(wayer[headsub].sita+wayer[headsub].sitb,0,5,headsub,tailsub);
 83                     vis[wayer[headsub].sita+wayer[headsub].sitb][0]=1;
 84                 }
 85             }
 86             //6
 87             if (vis[wayer[headsub].sita][0]==0)
 88             {
 89                 wayer[++tailsub]=STR(wayer[headsub].sita,0,6,headsub,tailsub);
 90                 vis[wayer[headsub].sita][0]=1;
 91             }
 92             ++headsub;
 93         }
 94     }
 95     if (headsub==tailsub+1)
 96     {
 97         cout<<"impossinle"<<endl;
 98     }
 99     else
100     {
101         int gathersub[10005];
102         int subnum=0;
103         gathersub[++subnum]=wayer[headsub].selfsub;
104         int resub=wayer[headsub].fathersub;
105         while (1)
106         {
107             if (resub==1)
108             {
109                 break;
110             }
111             gathersub[++subnum]=resub;
112             resub=wayer[resub].fathersub;
113         }
114         reverse(gathersub+1,gathersub+subnum+1);
115         cout<<subnum<<endl;
116         for (int i=1;i<=subnum;i++)
117         {
118             cout<<wayname[wayer[gathersub[i]].waynum]<<endl;
119         }
120     }
121     return 0;
122 }

 1 #include<bits/stdc++.h>
 2 #include<cstring>
 3 #include<string>
 4 using namespace std;
 5 struct STR{
 6     int a,b,fsub,step;
 7     STR (int aa,int bb,int ffsub,int sstep):
 8     a(aa),b(bb),fsub(ffsub),step(sstep){}
 9     STR(){}
10 }wayer[10005];
11 string wayname[6]={"FILL(1)","POUR(1,2)","DROP(1)","FILL(2)","POUR(2,1)","DROP(2)"};
12 int vis[105][105];
13 int main()
14 {
15     int a,b,c;
16     cin>>a>>b>>c;
17     memset (vis,0,sizeof(vis));
18     int hsub=0,tsub=0;
19     wayer[tsub++]=STR(0,0,-1,0);
20     vis[0][0]=1;
21     STR to,fo;
22     while (hsub<tsub)
23     {
24         to=wayer[hsub];//取出队头;
25         if (to.a==c||to.b==c){ break; }
26         for (int i=0;i<6;i++)//对队伍进行拓展;
27         {
28             if (i==0){ fo.a=a; fo.b=to.b;}
29             else if (i==1)
30             {
31                 fo.a=to.a+to.b;
32                 if (fo.a>b){ fo.a=to.a+to.b-b; fo.b=b;}
33                 else { fo.b=fo.a; fo.a=0;}
34             }
35             else if (i==2) { fo.a=0; fo.b=to.b;}
36             else if (i==3) { fo.b=b; fo.a=to.a;}
37             else if (i==4)
38             {
39                 fo.b=to.a+to.b;
40                 if (fo.b>a){ fo.b=to.a+to.b-a; fo.a=a;}
41                 else {fo.a=fo.b; fo.b=0; }
42             }
43             else if (i==5){ fo.b=0; fo.a=to.a;}
44             if (vis[fo.a][fo.b]==0)
45             {
46                 vis[fo.a][fo.b]=1;
47                 wayer[tsub++]=STR(fo.a,fo.b,hsub,i);
48             }
49         }
50         hsub++;//去除队头;
51     }
52     if (hsub>=tsub){cout<<"impossible"<<endl;}
53     else
54     {
55         int gsuber[10005],gsub=0,msub;//收集步骤下标;
56         gsuber[gsub++]=hsub;
57         msub=wayer[hsub].fsub;
58         while (msub!=-1)
59         {
60             gsuber[gsub++]=msub;
61             msub=wayer[msub].fsub;
62         }
63         reverse(gsuber,gsuber+gsub);
64         for (int i=0;i<gsub;i++)
65         {
66             cout<<wayname[gsuber[i]]<<endl;
67         }
68     }
69     return 0;
70 }

 

分别是我两次写的,虽然都错了,但让我知道了:尽量不要过长的命名,否则像第一次写的很繁杂;

 
posted @ 2022-01-26 12:20  次林梦叶  阅读(239)  评论(0)    收藏  举报