Knights of Ni(两次bfs)

来源:互联网 发布:香橙派 ubuntu 编辑:程序博客网 时间:2024/05/06 20:59

Bessie is in Camelot and has encountered a sticky situation: she needs to pass through the forest that is guarded by the Knights of Ni. In order to pass through safely, the Knights have demanded that she bring them a single shrubbery. Time is of the essence, and Bessie must find and bring them a shrubbery as quickly as possible.

Bessie has a map of of the forest, which is partitioned into a square grid arrayed in the usual manner, with axes parallel to the X and Y axes. The map is W x H units in size (1 <= W <= 1000; 1 <= H <= 1000). 

The map shows where Bessie starts her quest, the single square where the Knights of Ni are, and the locations of all the shrubberies of the land. It also shows which areas of the map can be traverse (some grid blocks are impassable because of swamps, cliffs, and killer rabbits). Bessie can not pass through the Knights of Ni square without a shrubbery. 

In order to make sure that she follows the map correctly, Bessie can only move in four directions: North, East, South, or West (i.e., NOT diagonally). She requires one day to complete a traversal from one grid block to a neighboring grid block. 

It is guaranteed that Bessie will be able to obtain a shrubbery and then deliver it to the Knights of Ni. Determine the quickest way for her to do so.
Input
Line 1: Two space-separated integers: W and H. 

Lines 2..?: These lines describe the map, row by row. The first line describes the most northwest part of the map; the last line describes the most southeast part of the map. Successive integers in the input describe columns of the map from west to east. Each new row of a map's description starts on a new input line, and each input line contains no more than 40 space-separated integers. If W <= 40, then each input line describes a complete row of the map. If W > 40, then more than one line is used to describe a single row, 40 integers on each line except potentially the last one. No input line ever describes elements of more than one row. 

The integers that describe the map come from this set: 
0: Square through which Bessie can travel 
1: Impassable square that Bessie cannot traverse 
2: Bessie's starting location 
3: Location of the Knights of Ni 
4: Location of a shrubbery
Output
Line 1: D, the minimum number of days it will take Bessie to reach a shrubbery and bring it to the Knights of Ni.
Sample Input
8 44 1 0 0 0 0 1 00 0 0 1 0 1 0 00 2 1 1 3 0 4 00 0 0 4 1 1 1 0
Sample Output
11
Hint
Explanation of the sample: 

Width=8, height=4. Bessie starts on the third row, only a few squares away from the Knights. 

Bessie can move in this pattern to get a shrubbery for the Knights: N, W, N, S, E, E, N, E, E, S, S. She gets the shrubbery in the northwest corner and then makes her away around the barriers to the east and then south to the Knights.

题意:

在一个矩阵中,每个小方块都代表不同东西0代表可以通行,1代表障碍,2代表起始位置,3代表终点,4代表灌木,问由起点到终点并且经过中途必须经灌木的最小步数是多少?

思路:

以每个4为起点,分别bfs起点和终点,然后两和想加,即得出起点到终点的距离,然后在枚举每个4点,寻找最小的那个。开始是这样得思路,但是这样会超时,,,,,,,,

正确思路:从起始点往灌木搜然后再从终点往灌木搜。

正确代码:

#include<iostream>#include<string>#include<cstdio>#include<algorithm>#include<cmath>#include<iomanip>#include<queue>#include<cstring>#include<map>using namespace std;typedef long long ll;#define pi acos(-1.0)#define inf 0x7fffffff#define M 1005int n,sx,sy,ex,ey,mx,my,x,y,cnt,num,ii;int a[M][M];bool ok[M][M];bool f1;int dx[4]={0,0,1,-1};int dy[4]={1,-1,0,0};struct node {    int x,y,s;}p[1000000];void bfs2(){    queue<node>Q;    node t1,t2;    t1.x=ex; t1.y=ey; t1.s=0;    ok[t1.x][t1.y]=true;    Q.push(t1);    while(!Q.empty())    {        t1=Q.front();        Q.pop();        if(a[t1.x][t1.y]==4)        {            int ttt;            for(int r=1;r<=num;r++)            if(t1.x==p[r].x&&t1.y==p[r].y) {ttt=p[r].s; break;}            if(cnt>t1.s+ttt) cnt=t1.s+ttt;            ii++;            if(ii==num) return;            continue;        }        for(int k=0;k<4;k++)        {            t2.x=t1.x+dx[k];            t2.y=t1.y+dy[k];            if(t2.x>=1&&t2.x<=x&&t2.y>=1&&t2.y<=y)            {                if(!ok[t2.x][t2.y]&&a[t2.x][t2.y]!=1)                {                    ok[t2.x][t2.y]=true;                    t2.s=t1.s+1;                    Q.push(t2);                }            }        }    }}void bfs1(){    queue<node>Q;    node t1,t2;    t1.x=sx; t1.y=sy; t1.s=0;    ok[sx][sy]=true;    Q.push(t1);    while(!Q.empty())    {        t1=Q.front();        Q.pop();        if(a[t1.x][t1.y]==4)        {            for(int r=1;r<=num;r++)            if(t1.x==p[r].x&&t1.y==p[r].y) {p[r].s=t1.s;; break;}            ii++;            if(ii==num) return;            continue;        }        for(int k=0;k<4;k++)        {            t2.x=t1.x+dx[k];            t2.y=t1.y+dy[k];            if(t2.x>=1&&t2.x<=x&&t2.y>=1&&t2.y<=y)            {                if(!ok[t2.x][t2.y]&&a[t2.x][t2.y]!=1)                {                    ok[t2.x][t2.y]=true;                    t2.s=t1.s+1;                    Q.push(t2);                }            }        }    }}int main(){    int i,j;    num=0;    scanf("%d%d",&y,&x);    for(i=1;i<=x;i++)        for(j=1;j<=y;j++)    {        scanf("%d",&a[i][j]);        if(a[i][j]==2){sx=i;sy=j;}        else if(a[i][j]==3) {ex=i;ey=j;}        else if(a[i][j]==4)        {            p[++num].x=i;            p[num].y=j;        }    }    cnt=inf; ii=0;    memset(ok,false,sizeof(ok));    bfs1();    memset(ok,false,sizeof(ok));    ii=0;    bfs2();    printf("%d",cnt);    return 0;}
TLE代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <string>#include <map>#include <stack>#include <vector>#include <set>#include <queue>#include <iomanip>#define maxn 1010#define mod 1000000000#define INF 0x3f3f3f3f#define exp 1e-6#define pi acos(-1.0)using namespace std;int dir[4][2]={{0,1},{0,-1},{-1,0},{1,0}};struct point{int x,y;int moves;};queue<point>q;int ex,ey,sx,sy;int w,h;int mp[maxn][maxn];bool vis[maxn][maxn],vis1[maxn][maxn];struct mark{int xx;int yy;}m[7005];int bfs1(point s){    vis[s.x][s.y]=1;    int i;    point head,t;    q.push(s);    while(!q.empty())    {        head=q.front();        q.pop();        if(head.x==ex&&head.y==ey)return head.moves;        for(i=0;i<4;i++)        {            int x=head.x+dir[i][0];            int y=head.y+dir[i][1];            if(x>=0&&x<h&&y>=0&&y<w&&mp[x][y]!=1&&!vis[x][y])            {                vis[x][y]=1;                t.x=x;                t.y=y;                t.moves=head.moves+1;                q.push(t);            }        }    }}int bfs2(point s){    vis1[s.x][s.y]=1;    int i;    point head,t;    q.push(s);    while(!q.empty())    {        head=q.front();        q.pop();        if(head.x==sx&&head.y==sy)return head.moves;        for(i=0;i<4;i++)        {            int x=head.x+dir[i][0];            int y=head.y+dir[i][1];            if(x>=0&&x<h&&y>=0&&y<w&&mp[x][y]!=1&&!vis1[x][y])            {                vis1[x][y]=1;                t.x=x;                t.y=y;                t.moves=head.moves+1;                q.push(t);            }        }    }}int main(){    ios::sync_with_stdio(false);    point start;    int i,j;    int k=0;    scanf("%d%d",&w,&h);    for(i=0;i<h;i++)    for(j=0;j<w;j++)    {        scanf("%d",&mp[i][j]);        if(mp[i][j]==3){ex=i,ey=j;}        else if(mp[i][j]==2){sx=i,sy=j;}        else if(mp[i][j]==4){m[k].xx=i,m[k++].yy=j;}    }    int minn=INF;    for(i=0;i<k;i++)    {        int sum;        memset(vis,0,sizeof(vis));        memset(vis1,0,sizeof(vis1));        start.x=m[i].xx;        start.y=m[i].yy;        start.moves=0;        while(!q.empty()) q.pop();        int sum1=bfs1(start);        while(!q.empty()) q.pop();        int sum2=bfs2(start);        sum=sum1+sum2;        if(minn>sum)minn=sum;    }    printf("%d",minn);    return 0;}



原创粉丝点击