codeforces 793B - Igor and his way to work(dfs、bfs)

题目链接:http://codeforces.com/problemset/problem/793/B

题目大意:告诉你起点和终点,要求你在只能转弯两次的情况下能不能到达终点。能就输出“YES”,不能就输出“NO”。

解题思路:这算是经典的转弯题了,接近半年没写搜索题了,,所以今天先拿这道题开刀吧。这个题关键就是“判重”,如何记录走过的点。我们可以开个三维数组,记录各个坐标各个方向上的转弯数,如果下次在到这个点这个方向,那就比较转弯数,如果这次转弯数大于等于已经记录的转弯数那就不用再找下去了,因为这次能走到的地方,上次肯定也能走到。估计一下时间复杂度大概为O(2n)。

dfs:

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 const int N=1e3+5;
 5 int m,n;
 6 bool flag=false;
 7 char map[N][N];
 8 int vis[N][N][5];//*关键*用来标记走过的点,记录该点朝着各方向转弯数
 9 int d[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
10
11 void dfs(int x,int y,int dir,int cnt){
12     if(x<=0||x>m||y<=0||y>n||cnt>2)
13         return;
14     if(vis[x][y][dir]<=cnt)//如果这个位置这个方向已经走过,且用了更小的转弯数,那就不用再走这个点了
15         return;
16     if(map[x][y]==‘T‘){
17         flag=true;
18         return;
19     }
20     if(map[x][y]!=‘.‘&&map[x][y]!=‘S‘)
21         return;
22     vis[x][y][dir]=cnt;
23     for(int i=0;i<4;i++) {
24         int x1=x+d[i][0];
25         int y1=y+d[i][1];
26         if(dir==-1)
27             dfs(x1,y1,i,cnt);
28         else if(dir!=i)
29             dfs(x1,y1,i,cnt+1);
30         else
31             dfs(x1,y1,i,cnt);
32     }
33 }
34
35 int main(){
36     int index,indey;
37     scanf("%d %d",&m,&n);
38     getchar();
39     for(int i=1;i<=m;i++){
40         for(int j=1;j<=n;j++){
41             scanf("%c",&map[i][j]);
42             if(map[i][j]==‘S‘){
43                 index=i;
44                 indey=j;
45             }
46         }
47         getchar();
48     }
49     memset(vis,0x3f,sizeof(vis));//转弯数初始化为无限大
50     dfs(index,indey,-1,0);//-1表示开始位置没有方向
51     if(flag)
52         printf("YES\n");
53     else
54         printf("NO\n");
55 }

bfs,跟上面差不多的:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<queue>
 4 using namespace std;
 5 const int N=1e3+5;
 6 int vis[N][N][5];
 7 int d[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
 8 char map[N][N];
 9 int m,n;
10 bool flag=false;
11
12 struct node{
13     int x,y,dir,cnt;
14 }now,t,pre;
15 //int num=0;
16 void bfs(int stax,int stay){
17     queue<node>q;
18     t.x=stax;
19     t.y=stay;
20     t.dir=-1;
21     t.cnt=0;
22     q.push(t);
23     while(!q.empty()){
24         pre=q.front();
25         q.pop();
26         for(int i=0;i<4;i++){
27             int x=pre.x+d[i][0];
28             int y=pre.y+d[i][1];
29             int cnt;
30             if(pre.dir==-1)//判断一下上次方向和当前要走的方向的关系
31                 cnt=0;
32             else if(pre.dir==i)
33                 cnt=pre.cnt;
34             else if(pre.dir!=i)
35                 cnt=pre.cnt+1;
36             if(x<=0||x>m||y<=0||y>n||cnt>2)
37                 continue;
38             if(map[x][y]==‘T‘){//到达终点
39                 flag=true;
40                 return;
41             }
42             if(map[x][y]!=‘S‘&&map[x][y]!=‘.‘)
43                 continue;
44             if(vis[x][y][i]<=cnt)//这个点这个方向已经有更优方案了
45                 continue;
46             vis[x][y][i]=cnt;
47             now.x=x;
48             now.y=y;
49             now.dir=i;
50             now.cnt=cnt;
51 //            num++;
52 //            printf("%d\n",num);
53             q.push(now);
54         }
55     }
56 }
57 int main(){
58     int index,indey;
59     scanf("%d %d",&m,&n);
60     getchar();
61     for(int i=1;i<=m;i++){
62         for(int j=1;j<=n;j++){
63             scanf("%c",&map[i][j]);
64             if(map[i][j]==‘S‘){
65                 index=i;
66                 indey=j;
67             }
68         }
69         getchar();
70     }
71     memset(vis,0x3f,sizeof(vis));
72     bfs(index,indey);
73     if(flag)
74         printf("YES\n");
75     else
76         printf("NO\n");
77 } 
时间: 2024-11-07 06:53:03

codeforces 793B - Igor and his way to work(dfs、bfs)的相关文章

Codeforces 453C Little Pony and Summer Sun Celebration dfs树上构造

题目链接:点击打开链接 题意: 给定一个无向图 任选一个起点,使得访问每个点的次数奇偶与最后一行的输入一致 思路: 选一个奇数点作为起点 dfs树一下,若子节点不满足则先走到子节点再回来 如此就能保证所有子节点合法 这样dfs结束后最多只有根节点不满足,随便找一个与根相连的点调整一下. #include <stdio.h> #include <string.h> #include <iostream> #include <math.h> #include &

Codeforces 747F Igor and Interesting Numbers dp

Igor and Interesting Numbers 枚举每一位, 用dp去算方案数. #include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair&

CodeForces 598D Igor In the Museum

暴力DFS预处理答案 #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> using namespace std; const int maxn=1000+10; char s[maxn][maxn]; struct X { int x,y; X(int a,int b) {

Codeforces 747F Igor and Interesting Numbers DP 组合数

题意:给你一个数n和t,问字母出现次数不超过t,第n小的16进制数是多少. 思路:容易联想到数位DP, 然而并不是...我们需要知道有多少位,在知道有多少位之后,用试填法找出答案.我们设dp[i][j]为考虑前i种字母,已经占了j个位置的方案数.那么dp[i][j] += dp[i - 1][j - k] * C[len - j + k][k],k的范围为[0, limit[k]].意思是我们暴力枚举第i个字母放多少个,然后排列组合. 这个题有一个细节需要注意,因为最高为一定不为0,所以我们试填

Codeforces Round #360 (Div. 1)A (二分图&dfs染色)

题目链接:http://codeforces.com/problemset/problem/687/A 题意:给出一个n个点m条边的图,分别将每条边连接的两个点放到两个集合中,输出两个集合中的点,若不可能则输出-1: 思路:通过画图我们不难发现,图中没有出现长度为奇数的环则是可行的,反之则是不行的.那么现在我们只需判断有木有长度为偶数的环即可. 对于这点我们可以直接用dfs搜索+染色,对于当前标记为1的点,我们将其所有儿子标记为2, 对于当前标记为2的点,将其所有儿子标记为1,若出现某个节点的标

CodeForces 510 B. Fox And Two Dots(DFS 啊)

题目链接:http://codeforces.com/problemset/problem/510/B Fox Ciel is playing a mobile puzzle game called "Two Dots". The basic levels are played on a board of size n?×?m cells, like this: Each cell contains a dot that has some color. We will use diff

Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+树状数组

C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/problem/C Description Iahub likes trees very much. Recently he discovered an interesting tree named propagating tree. The tree consists of n nodes numb

codeforces 570 D. Tree Requests 树状数组+dfs搜索序

链接:http://codeforces.com/problemset/problem/570/D D. Tree Requests time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Roman planted a tree consisting of n vertices. Each vertex contains a low

Codeforces Round #480 (Div. 2) C 贪心 D 数字、思维 E 树上倍增

Codeforces Round #480 (Div. 2) C. Posterized 题意: 给出 n 个数,都是区间 [0,255] 内的数,要你把 [0,255] 划分成多个长度 <=k 的不重叠的子区间.每个数必须包含在一个子区间内,且这个数的价值是这个子区间的左端点.要你输出这 n 数的价值,且这 n 个价值字典序要最小. tags: 首先很明显字典序最小,那对于第 i 个数 p[i] 定它的区间时,左端点肯定要尽可能小.所以我们直接枚举区间 [ p[i]-k+1, p[i] ] 定