8.1搜索专练DFS和BFS

这是第一次全部做出来的依次练习了,有一些都是做过两遍了的,但是还是错了几回,更多时候我还是应该多注意下细节,就好像章爷笑我 的一样,像什么vis[]标记没清0,什么格式错误,还有什么题目没看清,还是的注意一下了。

地址: 8.1搜索练习

Problem A POJ 2488

A Knight's Journey

题目大意就是说帮你给你个P*Q的棋盘,让马一次全部走完,每个点只能走一次,而且要按照字典序输出(这句话最坑!!!)。

这道题做过了两三次了,却老是被那句“字典序输出”给坑死。第一次看到这道题的时候,看到他说的字典序还以为是要让起点最小(虽然现在明白任何一个点作为起点都是可以到达终点的,只要里面有一条路可以遍历完),然后高高兴兴的枚举了起点,心想好简单叽里呱啦就敲完了,测试样例!过了!提交!WA了!然后就回头看代码,检查实在是无力了,在网上一搜,发现别人只用0,0,做起点就过了,马上改了提交!!!还是WA!!心力憔悴的我无力了,有重新找别人的代码,看到别人代码原来还有一小段注释

int dir[8][2]={-2,-1,-2,1,-1,-2,-1,2,1,-2,1,2,2,-1,2,1};  /*注意此处的数组数据, 为了保证每次的探索都是 符合字典序的*/

然后才慢慢明白什么叫字典序输出,其实就是要让每一步走的位置要是在能够遍历每个点的前提下,尽量让字典序小。大家可以慢慢体会下。

贴代码:180 KB     16 ms

 1 #include <stdio.h>
 2 #include <string.h>
 3 int vis[30][30];
 4 
 5 const int d[8][2] = {{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}};
 6 int m,n,num,ans[900],IsFind;
 7 
 8 
 9 void dfs(int x,int y)
10 {
11     if(x<0 || x>=m || y<0 || y>=n || vis[x][y] || IsFind) return ;
12     vis[x][y] = 1;
13     ans[num++] = x*n+y;
14     if(num == m*n){IsFind = 1; return;}
15     for(int i=0;i<8 && !IsFind;i++)
16     {
17         dfs(x+d[i][0], y+d[i][1]);
18     }
19     if(!IsFind)
20     {
21         num--;
22         vis[x][y]=0;
23     }
24 }
25 
26 int main()
27 {
28     int Case,T=0;
29     while(~scanf("%d", &Case))while(Case--)
30     {
31         memset(vis,0,sizeof(vis));
32         scanf("%d%d", &n, &m);
33         IsFind = 0;
34         num=0;
35         dfs(0,0);
36         printf("Scenario #%d:\n", ++T);
37         if(!IsFind)printf("impossible");
38         else for(int i=0;i<num;i++)
39         {
40             printf("%c%d", ans[i]/n+'A', ans[i]%n+1);
41         }
42         printf("\n\n");
43         if(!Case)T=0;
44     }
45     return 0;
46 }
View Code

 

 

Problem B Avoid The Lakes

Avoid The Lakes

简单的DFS求最大相连块  392 KB  16 ms

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <queue>
 4 #define MAX(a,b) ((a) > (b) ? (a) : (b))
 5 using namespace std;
 6 
 7 const int d[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
 8 int N,M,K;
 9 int Map[105][105],vis[105][105];
10 
11 int DFS(int x,int y)
12 {
13     if(x<0 || x>=N || y<0 || y>=M || vis[x][y] || Map[x][y])return 0;
14     int area = 1;
15     vis[x][y] = 1;
16     for(int i=0;i<4;i++)
17     {
18         area += DFS(x+d[i][0], y+d[i][1]);
19     }
20     return area;
21 }
22 
23 int main()
24 {
25     while(~scanf("%d%d%d",&N,&M,&K))
26     {
27         memset(Map,1,sizeof(Map));
28         memset(vis,0,sizeof(vis));
29         int a,b;
30         for(int i=0;i<K;i++)
31         {
32             scanf("%d%d", &a,&b);
33             Map[a-1][b-1] = 0;
34         }
35         int ans = 0;
36         for(int i=0;i<N;i++)
37         {
38             for(int j=0;j<M;j++)if(!vis[i][j] && !Map[i][j])
39             {
40                 int temp = DFS(i,j);
41                 ans = MAX(ans, temp);
42             }
43         }
44         printf("%d\n", ans);
45     }
46     return 0;
47 }
View Code

 

 

Problem C Dungeon Master

只是将求最短距离从二维增加到三维而已,数组加一维便可以实现436 KB16 ms

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 using namespace std;
 5 
 6 const int Dir[6][3] = {{0,0,1},{0,0,-1},{0,1,0},{0,-1,0},{1,0,0},{-1,0,0}};
 7 struct node
 8 {
 9     int x,y,z;
10     int step;
11 }Start;
12 char Map[35][35][35];
13 int vis[35][35][35];
14 int L,R,C;
15 
16 void readData()
17 {
18     memset(vis,0,sizeof(vis));
19     int IsFind_S=0;
20     for(int i=0;i<L;i++)
21     {
22         for(int j=0;j<R;j++)
23         {
24             scanf("%s",Map[i][j]);
25             for(int k=0;k<C && !IsFind_S;k++) if(Map[i][j][k] == 'S')
26             {
27                 Start.x = i;
28                 Start.y = j;
29                 Start.z = k;
30                 vis[i][j][k] = 1;
31                 Start.step = 0;
32                 IsFind_S = 1;
33             }
34         }
35     }
36 }
37 
38 int BFS()
39 {
40     queue<node>q;
41     q.push(Start);
42     while(!q.empty())
43     {
44         node u = q.front();
45         q.pop();
46         int x = u.x, y = u.y, z = u.z;
47         if(Map[x][y][z] == 'E')return u.step;
48         for(int i=0;i<6;i++)
49         {
50             int nx = x + Dir[i][0], ny = y + Dir[i][1], nz = z + Dir[i][2];
51             if(nx>=0 && nx<L && ny>=0 && ny<R && nz>=0 && nz < C && Map[nx][ny][nz]!='#' && !vis[nx][ny][nz])
52             {
53                 vis[nx][ny][nz] = 1;
54                 node v;
55                 v.x = nx; v.y = ny; v.z = nz; v.step = u.step+1;
56                 q.push(v);
57             }
58         }
59     }
60     return 0;
61 }
62 
63 int main()
64 {
65     while(scanf("%d%d%d%*c", &L, &R, &C) && (L||R||C))
66     {
67         readData();
68         int ans = BFS();
69         if(!ans)printf("Trapped!\n");
70         else printf("Escaped in %d minute(s).\n",ans);
71     }
72     return 0;
73 }
View Code

 

 

Problem D Sum It Up

题目意思就是说给一个T和N个数,让你求出所有的可以让N个数里面找出一些数使得他们的和为T,求所有情况

由于题目说了每给一个数,这个数就只能用一次,就是说帮你给20,20,20,那么你可以用1个,2个或者3个20,但是你只用第1个或者只用第2个这两种情况都是一样的。这样的话我们每次储存时候就不要重复的储存每个数,而是另外开一个数组保存每个不一样的数,在开一个数组保存每个数的次数。那么在DFS的时候就按照每个不同的数出现的次数,从max~0一直到他们的和为T,就打印数组

代码里还有注释:228 KB 0 ms

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <queue>
 4 #define MAX(a,b) ((a) > (b) ? (a) : (b))
 5 using namespace std;
 6 
 7 int ans[15];
 8 int N,T,IsFind;
 9 int use[15],num[15],NumOfUse;//NumOdUse用来统计有多好个不同的数,Use放的是不同的数,num放的是每个不同的数出现的次数
10 int index,k;//index表示DFS到了use[index],ans总共有k个数
11 
12 void DFS(int sum)
13 {
14     if(sum > T)return ;//和已经大于目标值,不需要继续搜索下去了
15     if(sum == T)//找到了就打印出来
16     {
17         IsFind = 1;//找到了
18         for(int i=0;i<k;i++)//打印
19         {
20             printf("%d%c", ans[i], (i==k-1)? '\n' : '+');
21         }
22         return ;
23     }
24     if(index == NumOfUse)return;//已经找到了最后一个,任然不满足,返回
25     for(int i=num[index];i>=0;i--)//对于第num[index],枚举他出现的次数
26     {
27         for(int j=0;j<i;j++)ans[k+j] = use[index];//向ans里放入i个数
28         index+=1;k+=i;
29         DFS(sum+use[index-1]*i);
30         index-=1;k-=i;
31     }
32 }
33 
34 int main()
35 {
36     while(~scanf("%d%d", &T,&N) && N)
37     {
38         memset(num,0,sizeof(num));
39         memset(ans,0,sizeof(ans));
40         memset(use,0,sizeof(use));
41         scanf("%d", &use[0]);
42         num[0] = 1;
43         NumOfUse = 1;
44         int temp;
45         for(int i=1;i<N;i++)
46         {
47             scanf("%d", &temp);
48             if(temp == use[NumOfUse-1])num[NumOfUse-1]++;//由于题目保证输入时非升序,所以直接与前一个比较,相同,次数加1
49             else {use[NumOfUse] = temp; num[NumOfUse]++;NumOfUse ++;}//不同,数的个数加1
50         }
51         IsFind = 0;
52         printf("Sums of %d:\n",T);
53         DFS(0);
54         if(!IsFind)printf("NONE\n");
55     }
56     return 0;
57 }
View Code

 

 

Problem E N皇后问题

第一次,直接用白书的方法,超时

 1 #include <stdio.h>
 2 #include <string.h>
 3 int vis[3][25],ans,n;
 4 
 5 void dfs(int cur)
 6 {
 7     if(cur == n){ans++;return;}
 8     for(int i=0;i<n;i++)
 9     {
10         if(!vis[0][i] && !vis[1][i+cur] && !vis[2][cur-i+n])
11         {
12             vis[0][i] = vis[1][i+cur] = vis[2][cur-i+n] = 1;
13             dfs(cur+1);
14             vis[0][i] = vis[1][i+cur] = vis[2][cur-i+n] = 0;
15         }
16     }
17 }
18 
19 
20 int main()
21 {
22     while(~scanf("%d", &n) && n)
23     {
24         ans = 0;
25         memset(vis,0,sizeof(vis));
26         dfs(0);
27         printf("%d\n", ans);
28     }
29     return 0;
30 }
View Code

第二次,听了章爷的说法,打表,没有写  if(!n)break;WA了

 1 #include <stdio.h>
 2 #include <string.h>
 3 int ans[11] = {0,1,0,0,2,10,4,40,92,352,724};
 4 int main()
 5 {
 6     int n;
 7     while(~scanf("%d", &n))
 8     {
 9         printf("%d\n",ans[n]);
10     }
11     return 0;
12 }
View Code

第三次,终于过了228 KB15 ms

 1 #include <stdio.h>
 2 #include <string.h>
 3 int ans[11] = {0,1,0,0,2,10,4,40,92,352,724};
 4 int main()
 5 {
 6     int n;
 7     while(~scanf("%d", &n) && n)
 8     {
 9         printf("%d\n",ans[n]);
10     }
11     return 0;
12 }
View Code

 

 

Problem F Basic

此题我没有加入太多想法,有思路就敲了,所以写得有些挫,代码效率也不高,基本思路就是枚举每个点是否放上一个棋子,共有2^16种情况,然后就没放上一个就标记之后不能放上的点,找出者2^16中情况中可以放得数目最多的

其实也可以直接枚举每个点,放或者不放两种情况,搜索下一个点

代码 172 KB63 ms

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <queue>
 4 #define MAX(a,b) ((a) > (b) ? (a) : (b))
 5 using namespace std;
 6 
 7 int N;
 8 char Map[5][5],vis[5][5];
 9 const int d[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
10 
11 int main()
12 {
13     while(~scanf("%d", &N) && N)
14     {
15         for(int i=0;i<N;i++)
16         {
17             scanf("%s", Map[i]);
18         }
19         int Max = 0;
20         for(int state = 1;state < (1<<(N*N));state++)
21         {
22             memset(vis,0,sizeof(vis));
23             int ans = 0;
24             for(int i=0;i<(N*N);i++)
25             {
26                 if(((1<<i) & state)  &&  Map[i/N][i%N]!='X' && !vis[i/N][i%N])
27                 {
28                     ans++;
29                     vis[i/N][i%N] = 1;
30                     for(int k=0;k<4;k++)
31                     {
32                         int x = i/N +d[k][0], y = i%N+d[k][1];
33                         while(x>=0 && x<N && y>=0 && y<N && Map[x][y]!='X')
34                         {
35                             vis[x][y] = 1;
36                             x+=d[k][0];  y += d[k][1];
37                         }
38                     }
39                 }
40             }
41             Max = MAX(Max, ans);
42         }
43         printf("%d\n", Max);
44     }
45     return 0;
46 }
View Code

 

 

Problem GAsteroids!

 简单的三维BFS问题

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <queue>
 4 #define Is(a,b) (a>=0 && a<b)
 5 #define MAX(a,b) ((a) > (b) ? (a) : (b))
 6 using namespace std;
 7 
 8 const int Dir[6][3] = {{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};
 9 int vis[15][15][15],N;
10 struct node{int x,y,z,step;};
11 node Start,End;
12 char Map[15][15][15];
13 
14 int ReadData()
15 {
16     memset(Map, 0, sizeof(Map));
17     char str[10]={0};
18     scanf("%s %d%*c", str, &N);
19     for(int i=0;i<N;i++)
20     {
21         for(int j=0;j<N;j++)
22         {
23             scanf("%s", Map[i][j]);
24         }
25     }
26     int x,y,z;
27     scanf("%d%d%d",&x,&y,&z);
28     Start.x = z;   Start.y = y;   Start.z = x;
29     scanf("%d%d%d",&x,&y,&z);
30     End.x = z;   End.y = y;   End.z = x;
31     scanf("%s",str);
32     if(str[0] == 'E')return 1;
33     return 0;
34 }
35 
36 int BFS()
37 {
38     memset(vis, 0, sizeof(vis));
39     queue<node>q;
40     Start.step = 0;
41     q.push(Start);
42     node u, v;
43     vis[Start.x][Start.y][Start.z] = 1;
44     while(!q.empty())
45     {
46         u = q.front();
47         q.pop();
48         int x = u.x, y = u.y, z = u.z;
49         if(x == End.x && y == End.y && z == End.z)return u.step;
50         for(int i=0;i<6;i++)
51         {
52             int nx = x+Dir[i][0], ny = y+Dir[i][1], nz = z+Dir[i][2];
53             if(Is(nx,N) && Is(ny,N) && Is(nz, N) && !vis[nx][ny][nz] && Map[nx][ny][nz]!='X')
54             {
55                 vis[nx][ny][nz] = 1;
56                 v.x = nx;  v.y = ny;  v.z = nz;
57                 v.step = u.step+1;
58                 q.push(v);
59             }
60         }
61     }
62     return -1;
63 }
64 
65 int main()
66 {
67     while(ReadData())
68     {
69         int ans = BFS();
70         if(ans == -1)printf("NO ROUTE\n");
71         else printf("%d %d\n",N,ans);
72     }
73 }
View Code

 

posted @ 2013-08-01 15:30  再见~雨泉  阅读(271)  评论(0编辑  收藏  举报