[01bfs]

bfs可以O(V+E)求解边权全为1的图上最短路。
而当边权只有0或1时,使用其它最短路算法是有些浪费的,此时可以使用bfs的变种:0-1 bfs来快速求解,复杂度仍为O(V+E).

D. Labyrinth(CF 1064D)

给你一个n*m的迷宫,给出起始点,向左不超过L,向右不超过R。

求最多能走到的点的个数。

当我们单纯的dfs(int x,int y,int L,int R)  //起点,L,R的时候,肯定会tle 的

我们可知,从起始点开始,向上向下的消耗的价值,也就是边权都为0,而向左向右的边权都为1.

这时,只有0和1的图就可以用 01bfs来写。

用一个双端队列。deque<node>que。(node结点来储存信息和限制条件)

当边权为0时,就把这个点加入顶端。当边权为1时,把点加入尾端。

que.push_front();  que.pop_front();

que.push_back();

 

 

这道题就从起始点开始遍历,上下两个点加入顶端,左右两个点加入尾端。

求最多能遍历到的点的个数就可以了。

因为每个点最多只可能遍历一次,因此可以省去bok数组。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <set>
 6 #include <queue>
 7 #include <stack>
 8 #include <string>
 9 #include <cstring>
10 #include <vector>
11 #include <map>
12 #include<ctime>
13 //#include <unordered_map>
14 #define mem( a ,x ) memset( a , x ,sizeof(a) )
15 #define rep( i ,x ,y ) for( int i = x ; i<=y ;i++ )
16 #define lson  l ,mid ,pos<<1
17 #define rson mid+1 ,r ,pos<<1|1
18 using namespace std;
19 typedef long long ll ;
20 typedef pair<int ,int> pii;
21 typedef pair<ll ,int> pli;
22 const int inf = 0x3f3f3f3f;
23 const ll mod=998244353;
24 const int N=100000+50;
25 int n,m,r,c,L,R;
26 char s[2010][2010];
27 int bok[2010][2010];
28 int xx[4]={0,0,1,-1};
29 int yy[4]={1,-1,0,0};
30 struct node
31 {
32     int x,y,l,r;
33 }e;
34 deque<node>que;
35 int check(int xx,int yy)
36 {
37     if(xx<1||xx>n||yy<1|yy>m||bok[xx][yy]==1||s[xx][yy]=='*')
38         return 0;
39     return 1;
40 }
41 void dfs()
42 {
43     bok[r][c]=1;
44     que.push_front({r,c,L,R});
45     while(!que.empty())
46     {
47         e=que.front();    que.pop_front();
48         //cout<<e.x<<" "<<e.y<<" "<<e.l<<" "<<e.r<<endl;
49         for(int i=2;i<4;i++)
50         {
51             int _x=e.x+xx[i],_y=e.y+yy[i];
52             if(check(_x,_y))
53             {
54                 bok[_x][_y]=1;
55                 que.push_front({_x,_y,e.l,e.r});
56             }
57         }
58         int _x=e.x+xx[1],_y=e.y+yy[1];
59         if(check(_x,_y)&&e.l)
60             {
61                 bok[_x][_y]=1;
62                 que.push_back({_x,_y,e.l-1,e.r});
63             }
64         _x=e.x+xx[0],_y=e.y+yy[0];
65         if(check(_x,_y)&&e.r)
66             {
67                 bok[_x][_y]=1;
68                 que.push_back({_x,_y,e.l,e.r-1});
69             }
70     }
71 
72 }
73 int main()
74 {
75     scanf("%d%d%d%d%d%d",&n,&m,&r,&c,&L,&R);
76     for(int i=1;i<=n;i++)
77         scanf("%s",s[i]+1);
78     dfs();
79     int ans=0;
80     for(int i=1;i<=n;i++)
81         for(int j=1;j<=m;j++)
82             ans+=bok[i][j];
83     printf("%d\n",ans);
84 
85     return 0;
86 }
View Code

 

E. Nastya and Unexpected Guest(CF 1341E)

一条路上从0-n,其中有m个安全点,他们分别是di。给出绿灯时间g红灯时间r

1.在红灯时间上,不能走,且必须在安全点上面。

2.在绿灯时间上,必须走

3.除非到安全点才能够转弯,否则不能。

4.每秒走1m,求到达n的最短时间。

 

 

只有在路上完美的度过一个绿灯时间,并且最终点是安全点,才算答案。

设f[i][j] 分别为 到达 d[i] 点时,绿灯时间过了 j 秒,最少的完整红绿灯时间个数。

如果 j==0 且 n-d[i] <=g (当前绿灯时间没有,也就有几个完整的红绿灯时间,从d[i]点出发,能够直接到n点,也就是答案)

  ans=min(ans,f[i][j]*(g+r)+n-d[i]);  //完整的红绿灯个数*红绿灯时间 ,再加上最后一趟走的时间。

如果 j==g //正好过了一个绿灯时间。也就是正好一个红绿灯轮回

  f[i][0]=f[i][j]+1 //个数加一,并且要把这个点放进队列尾端。

  que.push_back();

  continue;

再从这个点 向左边的安全点 或者右边的安全点 走,转移一下,把这些状态都记录下来,其实是看 是否能走过一个完整的绿灯时间。

  f[p][v]=f[i][j]  //这时个数不加一,把这个点放进队列开头。

  que.push_front();

 

最后输出答案就好了。 队列里最多有 m*g 个状态。且因为求最优,每个点只会经过一次。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <set>
 6 #include <queue>
 7 #include <stack>
 8 #include <string>
 9 #include <cstring>
10 #include <vector>
11 #include <map>
12 #include<ctime>
13 //#include <unordered_map>
14 #define mem( a ,x ) memset( a , x ,sizeof(a) )
15 #define rep( i ,x ,y ) for( int i = x ; i<=y ;i++ )
16 #define lson  l ,mid ,pos<<1
17 #define rson mid+1 ,r ,pos<<1|1
18 using namespace std;
19 typedef long long ll ;
20 typedef pair<int ,int> pii;
21 typedef pair<ll ,int> pli;
22 const int inf = 0x3f3f3f3f;
23 const ll mod=998244353;
24 const int N=10000+50;
25 int n,m,d[N],g,r;
26 int bok[N][1010],f[N][1010];
27 ll ans=-1,res;
28 struct node
29 {
30     int p,v;
31 }e;
32 void dfs()
33 {
34     deque<node>que;
35     bok[0][0]=1;
36     que.push_front({0,0});
37     while(!que.empty())
38     {
39         e=que.front();  que.pop_front();
40         if(e.v==0)
41         {
42             if(n-d[e.p]<=g)
43             {
44                 res=1ll*f[e.p][e.v]*(g+r)+n-d[e.p];
45                 if(ans==-1||ans>res)
46                     ans=res;
47             }
48         }
49         if(e.v==g)
50         {
51             if(!bok[e.p][0])
52             {
53                 bok[e.p][0]=1;
54                 f[e.p][0]=f[e.p][e.v]+1;
55                 que.push_back({e.p,0});
56             }
57             continue;
58         }
59         if(e.p>1)
60         {
61             int p=e.p-1;
62             int v=e.v+d[e.p]-d[p];
63             if(v<=g&&!bok[p][v])
64             {
65                 bok[p][v]=1;
66                 f[p][v]=f[e.p][e.v];
67                 que.push_front({p,v});
68             }
69         }
70         if(e.p<m)
71         {
72             int p=e.p+1;
73             int v=e.v+d[p]-d[e.p];
74             if(v<=g&&!bok[p][v])
75             {
76                 bok[p][v]=1;
77                 f[p][v]=f[e.p][e.v];
78                 que.push_front({p,v});
79             }
80         }
81     }
82     printf("%lld\n",ans);
83 }
84 int main()
85 {
86     scanf("%d%d",&n,&m);
87     for(int i=1;i<=m;i++)
88         scanf("%d",&d[i]);
89     sort(d+1,d+m+1);
90     scanf("%d%d",&g,&r);
91     dfs();
92 
93     return 0;
94 }
View Code

 

Codeforces 590C Three States

posted @ 2020-05-28 17:07  kaike  阅读(1044)  评论(0编辑  收藏  举报