BFS搜索 poj 3126 3278 3669

BFS搜索以及DFS搜索都需要把扩展的节点限制在给定的范围内,否则可能RE

Prime Path

题意:一位傲娇首相要换门牌号。门牌号是四位数字,给定起始门牌号和终止门牌号,每次只能改变一位数字,并且改完必须仍为素数,问需要改变几次?

找最少的一般都是BFS鸭

注意不能用优先权队列,因为有可能要换成小的,也有可能要换成大的


#include<cstdio>
#include<queue>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=9999+10;
int d[5];
int prime[maxn];
bool vis[maxn];
struct point
{
    int x;
    int time;
};
point start,end2;
bool is_prime(int x)
{
   for(int i=2;i<=sqrt(x*1.0);i++)
   {
       if(x%i==0)
        return false;
   }
   return true;
}
void init()
{
    for(int i=1000;i<=maxn;i++)
        prime[i]=i;
    for(int i=1000;i<=maxn;i++)
    {
        if(is_prime(prime[i]))
            prime[i]=1;
        else
            prime[i]=0;
    }
}
int bfs()
{
     queue<point>q;
     point old,current;
     q.push(start);
     vis[start.x]=1;
     while(!q.empty())
     {
        old=q.front();
        q.pop();
        if(old.x==end2.x)
            return old.time;
        d[1]=old.x%10;
        d[2]=old.x/10%10;
        d[3]=old.x/100%10;
        d[4]=old.x/1000;
        //printf("%d %d %d %d\n",d[4],d[3],d[2],d[1]);
        for(int i=1;i<=4;++i)
        {
            for(int j=0;j<=9;++j)
            {
                if(i==4&&j==0) continue;
                if(i==1&&!(j&1)) continue;
                int tmp=d[i];
                d[i]=j;
                current.x=d[4]*1000+d[3]*100+d[2]*10+d[1];
                if(prime[current.x]&&!vis[current.x])
                {
                    current.time=old.time+1;
                    vis[current.x]=1;
                    q.push(current);
                }
                d[i]=tmp;           //注意必须要改回来

            }
        }
    }
    return -1;
}
int main()
{
    //freopen("out2.txt","w",stdout);
    memset(prime,0,sizeof(prime));

    int T;
    scanf("%d",&T);
    init();
    while(T--)
    {
        memset(vis,false,sizeof(vis));
        scanf("%d %d",&start.x,&end2.x);
        start.time=0;
        int ans=bfs();
        //printf("nas:%d\n",ans);
        if(ans!=-1)
             printf("%d\n",ans);
         else
             printf("Impossible\n");
    }
    return 0;
}

Catch That Cow

有两种状态转移的方式到达点X,求最短路  没有边权的时候用bfs  白皮:边权都相等的时候可以用广搜,这种情况下,priority_queue 和queue有相同效果,复杂度会发生变化

题意:农夫John站在X点,牛在K点,牛不动,农夫去抓他。一分钟内农夫可移动到X-1,X+1或者2*X,他需要多久能抓住牛?

我以为是个dp_(:з」∠)_

需要注意的是:不加合理范围判断的话会RE

//A
#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
const int NN=1e5+10;
int N,K;
bool vis[NN];
struct Node
{
    int x,flag;
}p1,p2;
queue<Node>q;
int bfs(int x)  //开始的起点
{
    memset(vis,false,sizeof(vis));
    p1.x=x,p1.flag=0;
    q.push(p1);
    vis[p1.x]=true;
    while(!q.empty())
    {
        p2=q.front();
        q.pop();
        if(p2.x==K) return p2.flag;
        else
        {
            //vis[p2.x]=true;  //取出来就标记为访问过
            Node tmp;
            tmp.x=p2.x+1; tmp.flag=p2.flag+1;
            if(tmp.x>=0&&tmp.x<=100000&&!vis[tmp.x]) {q.push(tmp);vis[tmp.x]=true;}  //不加范围的话会一直RE
            tmp.x=p2.x-1; tmp.flag=p2.flag+1;
            if(tmp.x>=0&&tmp.x<=100000&&!vis[tmp.x]) {q.push(tmp);vis[tmp.x]=true;}
            tmp.x=p2.x+p2.x; tmp.flag=p2.flag+1;
            if(tmp.x>=0&&tmp.x<=100000&&!vis[tmp.x]) {q.push(tmp);vis[tmp.x]=true;}
        }


    }
}
int main()
{
    cin>>N>>K;
    cout<<bfs(N)<<endl;
    return 0;
}

poj 3669 Meteor Shower

题意:女主在原点,即将来一批陨石雨,她想去一个不会有陨石砸下来的地方。陨石在T_i时间落在(x_i,y_i),会同时砸坏四个方向上的相邻土地,女主每单位时间可以移动到周围四个方向上没被砸坏的地方。问女主需要多久到达安全位置。

//https://www.cnblogs.com/iswoit/p/4446543.html
#include<iostream>
#include<algorithm>
#include<queue>
#include<string.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=800;
int time[N][N];//最早被炸的时间 //单独开了个数组存安全时间
int vis[N][N];
int dir[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
int m;
struct node
{
    int x,y,t;  //这里的t是它在遍历过程中是第几个,代表它的时间为几   我在遍历的过程中需要传递第几层访问这个量,用的结构体存
    node(int xx,int yy,int tt) :x(xx),y(yy),t(tt){}
    node(){}
};
bool inside(int x,int y)
{
    return x>=0&&y>=0;
}
bool safe(int x,int y,int t)
{
    if(t<time[x][y]) return true;
    else return false;
}
int bfs()
{
    queue<node> q;
    q.push(node(0,0,0));
    while(!q.empty())
    {
        node tmp=q.front();
        q.pop();
        int nx=tmp.x;
        int ny=tmp.y;
        if(vis[nx][ny]) continue;
        vis[nx][ny]=true;
        if(time[nx][ny]==INF) return tmp.t;         //到达安全地点
        else
        {
            for(int i=0;i<4;++i)
            {
                int nx=tmp.x+dir[i][0];
                int ny=tmp.y+dir[i][1];
                if(safe(nx,ny,tmp.t+1)&&inside(nx,ny)&&!vis[nx][ny])
                    q.push(node(nx,ny,tmp.t+1));
            }
        }
    }
    return -1;  //遍历完了没答案

}
int main()
{

   cin>>m;
   memset(vis,0,sizeof(vis));
   for(int i=0;i<N;++i)
     for(int j=0;j<N;++j)
     {
        time[i][j]=INF;
     }
     while(m--)
     {
         int x,y,t;
         cin>>x>>y>>t;
         time[x][y]=min(time[x][y],t);
         //cout<<"?"<<endl;
         for(int i=0;i<4;++i)
         {
             int nx=x+dir[i][0];
             int ny=y+dir[i][1];
             if(inside(nx,ny))//忘记写这个导致越界异常终止一次
               time[nx][ny]=min(time[nx][ny],t);

         }

     }
     if(time[0][0]==0) cout<<-1<<endl;
     else cout<<bfs()<<endl;
     return 0;
}

UVA-10603 Fill

这道题没拿下。。。LRJ上有源码,我明天再debug

倒水量指的是中间过程,注意注意,倒水过程中要么把i杯倒空,要么把j杯倒满

猜你喜欢

转载自blog.csdn.net/iroy33/article/details/88624927
今日推荐