2017.8.2——广搜(bfs)+队列的使用

今天做了三道广搜题,广搜比较顺手,或者是题目比较好理解,感觉比深搜思路清晰。

广搜需要用到队列queue,也是今天才真正觉得队列是个好东西。

一.队列

C++队列Queue类成员函数如下:

back()返回最后一个元素

empty()如果队列空则返回真

front()返回第一个元素

pop()删除第一个元素

push()在末尾加入一个元素

size()返回队列中元素的个数

queue 的基本操作举例如下:

       queue入队,如例:q.push(x); 将x 接到队列的末端。

queue出队,如例:q.pop(); 弹出队列的第一个元素,注意,并不会返回被弹出元素的值。

访问queue队首元素,如例:q.front(),即最早被压入队列的元素。

访问queue队尾元素,如例:q.back(),即最后被压入队列的元素。

判断queue队列空,如例:q.empty(),当队列空时,返回true。

访问队列中的元素个数,如例:q.size(—)

二.关于广搜步骤

从谁开始就把谁存到队列里,从它开始进行以后的步骤,广搜的话会遇到许多分支一类的东西,每遇到一个分支就要push进队列里,每次处理判断时都要处理最前边的,即front(),处理的同时也要将其删掉pop(),方便可以一直处理front()的那个。在处理的过程中也要判断找寻是否是结果,进行判断。。。。进行广搜要灵活将struct与queue结合使用,化繁为简。

广搜适用于最短最小问题,先搜到的路径一定是最小的。

三。广搜例题(一)

  catch that cow

一个数轴,一个人只能朝前走一步或者朝后走一步,或者走到现在位置的2倍,问抓到母牛的最小步数,假设牛不动。

思路:用struct储存人走到的位置,和人走到此地的步数。搜的时候加一减一乘二。走过的地点进行标记,重复走无意义。

代码如下:

#include
#include
#include
using namespace std;
int map[1000000]={0};
int n,k;

struct ppp
{
    int x;
    int step;
};
queuem;
int bfs(int x)
{
    ppp a,second;
    a.x=x;
    a.step=0;
    map[x]=1;
    m.push(a);
    while(m.empty()==0)
    {
        a=m.front();
        m.pop();
        if(a.x==k)
        return a.step;
        second=a;

        second.x=a.x+1;
        if(second.x>=0&&second.x<1000000&&map[second.x]==0)
        {
            second.step=a.step+1;
            m.push(second);
            map[second.x]=1;
        }

        second.x=a.x-1;
        if(second.x>=0&&second.x<1000000&&map[second.x]==0)
        {
            second.step=a.step+1;
            m.push(second);
            map[second.x]=1;
        }

 

        second.x=a.x*2;
        if(second.x>=0&&second.x<1000000&&map[second.x]==0)
        {
            second.step=a.step+1;
            m.push(second);
            map[second.x]=1;
        }
    }
    return 0;
}
int main()
{
    int shuchu;
    while(cin>>n>>k)
    {

        memset(map,0,sizeof(map));
        shuchu=bfs(n);
        cout<     }
    return 0;
}

广搜例题二:

Dungeon Master

Sample Input
 
   
3 4 5 S.... .###. .##.. ###.# ##### ##### ##.## ##... ##### ##### #.### ####E 1 3 3 S## #E# ### 0 0 0


 

Sample Output
 
   
Escaped in 11 minute(s). Trapped!

 

一个东西找出口,S是起点,E是终点,问能否逃出,若能,计算最短时间。

这个格子可以上下左右跳,也能隔着阶级跳,似乎很抽象,有#不能跳,似乎很抽象,我不知道怎么表示,后来同学提醒可以用三维数组,又说很简单,也硬着头皮写了些,之后一直由于各种细节问题,折腾了我一下午,虽然这道题很简单,思路也很清晰,但是充分展示出我的代码基础还是潜力很大的,哈哈哈哈,潜力。。。

下面是我的代码:

#include
#include
using namespace std;
int logal;
int endx,endy,endz,beginx,beginy,beginz;
int p,q,n;
char map[40][40][40];
struct io
{
    int x,y,z,step;
};
//int dx[6]={0,0,1,-1,0,0};
//int dy[6]={1,-1,0,0,0,0};
//int dz[6]={0,0,0,0,1,-1};
int next[6][3]={{0,1,0},{0,-1,0},{1,0,0},{-1,0,0},{0,0,1},{0,0,-1}};
int bfs(int a,int b,int c)
{
    int zuizhong;

    queuem;
    io t1,t2,t3;
    t1.x=a;
    t1.y=b;
    t1.z=c;
    t1.step=0;
    m.push(t1);
    map[t1.x][t1.y][t1.z]='#';//第一步走过要堵死,经常忘记第一步
    while(!m.empty())
    {
        t2=m.front();
        m.pop();
        for(int h=0;h<6;h++)
        {
            //t3.x=t2.x+dx[h];
            //t3.y=t3.y+dy[h];
            //t3.z=t3.z+dz[h];
            t3.x=t2.x+next[h][0];
            t3.y=t2.y+next[h][1];
            t3.z=t2.z+next[h][2];
            t3.step=t2.step+1;
            if(t3.x<0||t3.x>=n||t3.y<0||t3.y>=p||t3.z<0||t3.z>=q)
            continue;
            if(map[t3.x][t3.y][t3.z]!='#')
            {
                if(t3.x==endx&&t3.y==endy&&t3.z==endz)
                {
                    logal=1;//用logal作为是否有解的标志,方便输出
                    zuizhong=t3.step;
                }
                m.push(t3);
                map[t3.x][t3.y][t3.z]='#';//走过的一定要堵死,不能再走了
            }
        }
    }
    return zuizhong;
}


int main()
{
    while(cin>>n>>p>>q)
    {
        if(n==0&&p==0&&q==0)
        break;
        for(int i=0;i         {
            for(int j=0;j             {
                for(int r=0;r                 {
                    cin>>map[i][j][r];
                    if(map[i][j][r]=='S')
                    {
                        beginx=i;
                        beginy=j;
                        beginz=r;
                    }
                    if(map[i][j][r]=='E')
                    {
                        endx=i;
                        endy=j;
                        endz=r;
                    }
                }
            }
        }
        logal=0;
        bfs(beginx,beginy,beginz);
        if(logal==1)
        cout<<"Escaped in "<         else if(logal==0)
        cout<<"Trapped!"<     }
    return 0;
}
仔细看我的代码有注释掉的一部分我始终搞不清楚注释掉的和我写的差距的在哪,用注释掉的运行结果一直不对。。。。。

广搜例题三

Find The Multiple

这道题以前做过,题目比较坑人,根本读不出m是n的倍数来,nonzero multiple m of n大概是因为这句话,很多n的和吧,。。。原题目奉上,

Problem Description

Given a positive integer n, write a program to find out a nonzero multiple m of n whose decimal representation contains only the digits 0 and 1. You may assume that n is not greater than 200 and there is a corresponding m containing no more than 100 decimal digits.


 

Input

The input file may contain multiple test cases. Each line contains a value of n (1 <= n <= 200). A line containing a zero terminates the input.


 

Output

For each value of n in the input print a line containing the corresponding value of m. The decimal representation of m must not contain more than 100 digits. If there are multiple solutions for a given value of n, any one of them is acceptable.


 

Sample Input
 
   
2 6 19 0


 

Sample Output
 
   
10 100100100100100100 111111111111111111

 

有两种方法:一种广搜,好理解,一种数学找规律,都不错:

代码一:

#include
#include
using namespace std;
long long bfs(int k)
{
    queuem;//我的疑问是这句话放到头文件下面就MLE。。。。
    long long kkk;
    m.push(1);
    while(1)
    {

        kkk=m.front();
        if(kkk%k==0)
        return kkk;
        m.pop();
        m.push(kkk*10);
        m.push(kkk*10+1);
    }

}
int main()
{

    int n;
    while(cin>>n&&n!=0)
    {
        cout<     }
    return 0;

}

 

代码二:

#include
using namespace std;
int main()
{
    long long mod[600001]={0};
    int i,n;
    while(cin>>n&&n!=0)
    {
        for(i=1;;i++)
        {
            mod[i]=mod[i/2]*10+i%2;//本题精髓
            if(mod[i]%n==0)
            {
                cout<                 break;
            }
        }
    }
    return 0;
}

就是要用longlong,数组定的太小了。

 

 

 

今天就做了三道题,下午效率不大高,中午也没休息好。

感觉一群人奋斗还是挺激励我的。

给我的感觉是有些时候自己做的东西超出了想象,或许今天的题的确简单。

感恩,感谢,只想好好珍惜。

自己也不算渣,只是潜力很大而已,哈哈哈,感觉自学能力提升了不少。

英语读题能力还要练啊,真心不易~

明天会更认真的,提高效率,提高效率,要不然题真的做不完了。

10分的话今天给自己5分吧啊哈哈哈。

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

你可能感兴趣的:(2017暑假训练)