算法笔记--宽度优先搜索

来源:互联网 发布:sql数据库置疑怎么解决 编辑:程序博客网 时间:2024/05/29 10:10

poj 2312 Battle City

思路:从Y到T的最小turn。turn:走一步路算一种,开炮也算一种。
B:土墙,可以被炮打坏,打坏以后就不在了。
R:河流,不能通过。
S:铁墙:不能通过,也不能被炮弹打坏。
E:空格,可以直接走过去。

因此,用优先队列,每次取出turn最小的那个,进行操作。知道走到T为止。因为土墙可以仙贝打坏,在通过,因此如果遇到土墙,可以认为进项了两个turn,
而遇到E空格是,只需走一步,进行一个turn

#include<cstdio>#include<queue>#include<cstring>using namespace std;int cnv[4][2]={{1,0},{0,1},{-1,0},{0,-1}};struct Rac{    int x,y,cnt;    bool operator < (const Rac & p) const{       return cnt > p.cnt;    }  //优先取cnt 最小的那个元素};char mp[305][305];int visit[305][305];int sx,sy,tx,ty;int n,m;int main(){    while(scanf("%d %d",&m,&n),m!=0||n!=0)    {        getchar();        int i,j;        for(i=0;i<m;i++)        {            for(j=0;j<n;j++)            {                scanf("%c",&mp[i][j]);                if(mp[i][j]=='Y')                {                    sx=i;                    sy=j;                }                else if(mp[i][j]=='T')                {                    tx=i;                    ty=j;                }            }            getchar();        } //找出终点,起点        /* for(i=0;i<m;i++)        {            puts(mp[i]);        }*/        memset(visit,0,sizeof(visit));        priority_queue<Rac>q;//优先队列        Rac s;        s.x=sx;        s.y=sy;        s.cnt=0;        visit[sx][sy]=1;        q.push(s);        bool ok=false;        while(!ok&&q.empty()==false) //到达T 或队列为空是,停止        {            Rac t=q.top();            q.pop();            for(i=0;i<4;i++)  //上下左右操作            {                int x=t.x+cnv[i][0];                int y=t.y+cnv[i][1];                if(x>=0&&x<m&&y>=0&&y<n&&visit[x][y]==0&&mp[x][y]!='S'&&mp[x][y]!='R')//到达边界&&铁墙或河流不能通过                {                    if(mp[x][y]=='E') //为空格时                    {                        visit[x][y]=1;                        Rac t2;                        t2.x=x;                        t2.y=y;                        t2.cnt=t.cnt+1;                        q.push(t2);                    }                    else if(mp[x][y]=='B') //土墙时                    {                        visit[x][y]=1;                        Rac t2;                        t2.x=x;                        t2.y=y;                        t2.cnt=t.cnt+2;                        q.push(t2);                    }                    else if(mp[x][y]=='T') //到达终点                    {                        ok=true;                        printf("%d\n",t.cnt+1);                        break;                    }                }//if4            }        }        if(!ok) printf("-1\n"); //不能到达    }    return 0;}

codeforces723DLakes in Berland

给出一个地图:.是水,*是陆地,地图外边是海。这样里边就有湖泊,淡然与海相连的水就不是湖泊。问我要填掉一些湖泊,使得剩下的湖泊个数恰好为k,问最少要填多少水。
首先先DBS扫一次,把每个湖泊的面积以及“起始位置”记录下来。然后如果是与还相连的湖泊就吧大的面积看成极大值inf,然后这样从面积最小的开始填,使得剩下的非inf的湖泊个数恰好为k个。然后从“起始位置”再BFS扫一次把水给填上。最后输出最后的地图。

#include<cstdio>#include<cmath>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<queue>#include<vector>#include<map>#include<stack>#include<set>#define pi acos(-1.0)#define EPS 1e-6    //log(x)#define e exp(1.0); //2.718281828#define mod 1000000007#define INF 0x7fffffff#define inf 0x3f3f3f3ftypedef long long LL;using namespace std;int n,m,k;char mp[55][55];int x[4]={0,0,1,-1};int y[4]={1,-1,0,0};bool visit[55][55];struct wei{    int x,y;};struct jilu{ //用于记录湖泊信息    int x,y; //位置    int cnt;//面积    bool operator < (const jilu & p) const{        return cnt<p.cnt;    }}K[2500];int jilucnt;queue<wei>Q;void bfs(int i,int j){//扫出每个湖泊的面积以及起始位置    while(Q.empty()==false) Q.pop();    int cnt=1;    visit[i][j]=true;    bool ishai=false;    wei temp;    temp.x=i;temp.y=j;    Q.push(temp);    while(Q.empty()==false){        wei temp2=Q.front();        Q.pop();        for(int i=0;i<4;i++){            int nowx=temp2.x+x[i];            int nowy=temp2.y+y[i];            if(nowx<0||nowx>=n||nowy<0||nowy>=m){                ishai=true;                continue;            }            if(mp[nowx][nowy]=='.'&&visit[nowx][nowy]==false){                wei in;                in.x=nowx;                in.y=nowy;                Q.push(in);                cnt++;                visit[nowx][nowy]=true;            }        }    }    K[jilucnt].x=i;    K[jilucnt].y=j;    if(ishai==true)K[jilucnt].cnt=inf;    else K[jilucnt].cnt=cnt;    jilucnt++;}queue<wei>tian;void BFS2(int i,int j){ //填水BFS    while(tian.empty()==false) tian.pop();    wei temp;    temp.x=i;temp.y=j;    tian.push(temp);    while(tian.empty()==false){        wei temp2=tian.front();        tian.pop();        for(int i=0;i<4;i++){            int nowx=temp2.x+x[i];            int nowy=temp2.y+y[i];            if(nowx<0||nowx>=n||nowy<0||nowy>=m){                continue;            }            if(mp[nowx][nowy]=='.'){                wei tempp;                tempp.x=nowx;                tempp.y=nowy;                tian.push(tempp);            }        }        mp[temp2.x][temp2.y]='*';    } }int main(){    scanf("%d %d %d",&n,&m,&k);    for(int i=0;i<n;i++) scanf("%s",&mp[i]);    memset(visit,false,sizeof(visit));    jilucnt=0;    for(int i=0;i<=n;i++){        for(int j=0;j<m;j++){            if(mp[i][j]=='.'&&visit[i][j]==false){                //cout<<i<<" "<<j<<endl;                bfs(i,j);            }        }    }    sort(K,K+jilucnt);    //for(int i=0;i<jilucnt;i++) cout<<K[i].cnt<<" "<<K[i].x<<" "<<K[i].y<<endl;    while(K[jilucnt-1].cnt==inf) jilucnt--;    int ans=0;    for(int i=0;i<jilucnt-k;i++){        DFS2(K[i].x,K[i].y);        ans+=K[i].cnt;    }    cout<<ans<<endl;    for(int i=0;i<n;i++) puts(mp[i]);    return 0;}