DFS专题训练
分类:
IT文章
•
2025-02-03 22:57:07
参考书籍《算法竞赛入门到进阶》
poj2386 题目链接 http://poj.org/problem?id=2386
注意理解题目中的所谓的池塘,记录搜索次数即可。
AC代码:
1 #include <iostream>
2 #include <string.h>
3 using namespace std;
4 const int maxn=150;
5 char a[maxn][maxn];
6 int dx[8]={1,1,1,-1,-1,-1,0,0};
7 int dy[8]={1,-1,0,1,-1,0,1,-1};
8 int n,m;
9 void dfs(int x,int y)
10 {
11 a[x][y]='.';
12 for (int i = 0; i < 8; ++i)
13 {
14 int nx = x+dx[i];
15 int ny = y+dy[i];
16 if (nx>=0&&nx<n&&ny>=0&&ny<m&&a[nx][ny]=='W') dfs(nx,ny);
17 }
18 return ;
19 }
20 int main(int argc, char const *argv[])
21 {
22 cin>>n>>m;
23 int res=0;
24 for (int i = 0; i < n; ++i)
25 {
26 for (int j = 0; j < m; ++j)
27 {
28 cin>>a[i][j];
29 }
30 }
31 for (int i = 0; i < n; ++i)
32 {
33 for (int j = 0; j < m; ++j)
34 {
35 if (a[i][j]=='W')
36 {
37 dfs(i,j);
38 res++;
39 }
40 }
41 }
42 cout<<res<<endl;
43 return 0;
44 }
View Code
hdu2553 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2553
经典深搜问题
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3 int n,tot=0;
4 int col[12];
5 bool check(int c,int r)
6 {
7 for (int i = 0; i < r; ++i)
8 {
9 if (col[i]==c||(abs(col[i]-c)==abs(i-r))) return false;
10 }
11 return true;
12 }
13 void dfs(int r)
14 {
15 if (r==n)
16 {
17 tot++;
18 return ;
19 }
20 for (int c = 0; c < n; ++c)
21 {
22 if (check(c,r))
23 {
24 col[r]=c;
25 dfs(r+1);
26 }
27 }
28 }
29 int main(int argc, char const *argv[])
30 {
31 int ans[12]={0};
32 for (n = 0; n <= 10; ++n)
33 {
34 memset(col,0,sizeof(col));
35 tot=0;
36 dfs(0);
37 ans[n]=tot;
38 }
39 while(cin>>n)
40 {
41 if (n==0) return 0;
42 cout<<ans[n]<<endl;
43 }
44 return 0;
45 }
View Code
poj2531 题目链接:http://poj.org/problem?id=2531
题目要求两个集合中点的距离和最大,我们先假设都在一个集合,这样距离和为0,然后一个一个地往另外一个集合放,距离和变小则返回,变大继续,过程中不断更新最大值。
AC代码:
1 #include <iostream>
2 #include <string.h>
3 using namespace std;
4 const int inf=0x3f3f3f3f;
5 int a[25][25];
6 int g[25];
7 int res;
8 int n;
9 void dfs(int step,int sum)
10 {
11 g[step]=1;
12 int num=sum;
13 for (int i = 0; i < n; ++i)
14 {
15 if (g[i]==1) num-=a[step][i];
16 else num+=a[step][i];
17 }
18 res=max(res,num);
19 for (int i = step+1; i < n; ++i)
20 {
21 if (num>sum)
22 {
23 dfs(i,num);
24 g[i]=0;
25 }
26 }
27 }
28 int main(int argc, char const *argv[])
29 {
30 while(cin>>n)
31 {
32 memset(a,0,sizeof(a));
33 memset(g,0,sizeof(g));
34 for (int i = 0; i < n; ++i)
35 {
36 for (int j = 0; j < n; ++j)
37 {
38 cin>>a[i][j];
39 }
40 }
41 res=-0x3f3f3f3f;
42 dfs(0,0);
43 cout<<res;
44 }
45 return 0;
46 }
View Code
poj1416 题目链接:http://poj.org/problem?id=1416
预处理能被切成的情况,然后深搜,借鉴了网上的AC代码
AC代码:
1 #include <iostream>
2 #include <algorithm>
3 using namespace std;
4 #define MAXN 10000
5 int a,len,flag,rejected,k;
6 string b;
7 struct ss
8 {
9 int goal;
10 string str;
11 }score[MAXN],edge[10][10];
12 bool dfs(int now,int ret,string tmp_str)
13 {
14 if (ret>a||now>len) return false;
15 if (ret<=a&&now==len)
16 {
17 score[k].goal=ret;
18 score[k].str=tmp_str;
19 k++;
20 flag=1;
21 return true;
22 }
23 int next=now+1;
24 for (int i = next; i <=len; ++i) dfs(i,ret+edge[next][i].goal,tmp_str+" "+edge[next][i].str);
25 }
26 void build_map()
27 {
28 for (int i = 1; i <= len; ++i)
29 {
30 for (int j = i; j <= len; ++j)
31 {
32 if (i==j)
33 {
34 edge[i][j].goal=b[i]-'0';
35 edge[i][j].str=b[i];
36 }
37 else
38 {
39 edge[i][j].goal=edge[i][j-1].goal*10+b[j]-'0';
40 edge[i][j].str=edge[i][j-1].str+b[j];
41 }
42 }
43 }
44 }
45 bool cmp(ss aa,ss bb)
46 {
47 return aa.goal>bb.goal;
48 }
49 int main(int argc, char const *argv[])
50 {
51 while(cin>>a>>b)
52 {
53 if (!a&&b[0]=='0') break;
54 len = b.length();
55 b=" "+b;
56 build_map();
57 flag=rejected=0,k=1;
58 dfs(0,0,"");
59 if (k>1) sort(score+1,score+k,cmp);
60 if (score[1].goal==score[2].goal&&score[1].goal!=0) rejected=1;
61 if (flag&&!rejected) cout<<score[1].goal<<score[1].str<<endl;
62 else if (rejected) cout<<"rejected"<<endl;
63 else cout<<"error"<<endl;
64 }
65 return 0;
66 }
View Code
poj2676 题目链接:http://poj.org/problem?id=2676
九宫格,开三个数组,一个用来存同一行该数是否被用过,一个用来存同一列该数是否被用过,剩下一个用来存该宫格里是否被用过
AC代码:
1 #include <iostream>
2 #include <string.h>
3 using namespace std;
4 int mapp[10][10];//初始图
5 bool h[10][10];//行
6 bool l[10][10];//列
7 bool g[10][10];//格
8 bool flage=false;
9 bool dfs(int x,int y)
10 {
11 if (x==9)
12 {
13 flage=true;
14 return true;
15 }
16 if (mapp[x][y])
17 {
18 if(y==8) dfs(x+1,0);
19 else dfs(x,y+1);
20 if (flage) return true;
21 else return false;
22 }
23 else
24 {
25 int k=x/3*3+y/3;
26 for (int i = 1; i <= 9; ++i)//遍历1-9的9个数字
27 {
28 if (!h[x][i]&&!l[y][i]&&!g[k][i])
29 {
30 mapp[x][y]=i;
31 h[x][i]=true;
32 l[y][i]=true;
33 g[k][i]=true;
34 if(y==8) dfs(x+1,0);
35 else dfs(x,y+1);
36 if (flage)
37 {
38 return true;
39 }
40 else
41 {
42 mapp[x][y]=0;
43 h[x][i]=false;
44 l[y][i]=false;
45 g[k][i]=false;
46 }
47
48 }
49 }
50 }
51 return false;
52 }
53 int main(int argc, char const *argv[])
54 {
55 int t;
56 cin>>t;
57 while(t--)
58 {
59 memset(h,false,sizeof(h));
60 memset(l,false,sizeof(l));
61 memset(g,false,sizeof(g));
62 flage=false;
63 char c;
64 for (int i = 0; i < 9; ++i)
65 {
66 for (int j = 0; j < 9; ++j)
67 {
68 cin>>c;
69 mapp[i][j]=c-'0';
70 if (mapp[i][j])
71 {
72 int k=i/3*3+j/3;
73 h[i][mapp[i][j]]=true;
74 l[j][mapp[i][j]]=true;
75 g[k][mapp[i][j]]=true;
76 }
77 }
78 }
79 if(dfs(0,0))
80 {
81 for (int i = 0; i < 9; ++i)
82 {
83 for (int j = 0; j < 9; ++j)
84 {
85 cout<<mapp[i][j];
86 }
87 cout<<endl;
88 }
89 }
90 }
91 return 0;
92 }
View Code
poj1129 题目链接:http://poj.org/problem?id=1129
本题我没有使用深搜,用四色定理直接染色输出染色数即可,注意染同一颜色的是与其前被染的都不相邻才行,这是写代码时容易错的一个地方。
附样例:
5
A:BE
B:AC
C:BD
D:CE
E:AD
该样例应该输出3
AC代码:
1 #include <iostream>
2 #include <string.h>
3 #include <algorithm>
4 using namespace std;
5 struct node
6 {
7 char a;
8 int number;
9 bool f;
10 }aa[100];
11 bool mapp[30][30];
12 node bb[100];
13 int cmp(const node &a,const node &b)
14 {
15 return a.number>b.number;
16 }
17 int main(int argc, char const *argv[])
18 {
19 int t;
20 while(cin>>t)
21 {
22 memset(mapp,false,sizeof(mapp));
23 memset(aa,0,sizeof(aa));
24 string ss;
25 if (t==0) break;
26 else
27 {
28 for (int i = 0; i < t; ++i)
29 {
30 cin>>ss;
31 int len=ss.length();
32 aa[i].a=ss[0];
33 aa[i].number=len-2;
34 aa[i].f=false;
35 for (int j = 2; j < len; ++j)
36 {
37 mapp[ss[0]-'A'][ss[j]-'A']=true;
38 }
39 }
40 sort(aa,aa+t,cmp);
41 int num=0;
42 for (int i = 0; i < t; ++i)
43 {
44 if (aa[i].f==false)
45 {
46 int kk=0;
47 memset(bb,0,sizeof(bb));
48 aa[i].f=true;
49 bb[kk].a=aa[i].a;
50 kk++;
51 num++;
52 //cout<<num<<" "<<aa[i].a<<endl;
53 for (int j = 0; j < t; ++j)
54 {
55 if (aa[i].a-'A'==j) continue;
56 bool flage=true;
57 for (int ii = 0; ii < kk; ++ii)
58 {
59 if (mapp[bb[ii].a-'A'][j]!=false)
60 {
61 flage=false;
62 }
63 }
64 if (flage)
65 {
66 for (int k = 0; k < t; ++k)
67 {
68 if(aa[k].a==j+'A'&&aa[k].f==false)
69 {
70 aa[k].f=true;
71 bb[kk].a=aa[k].a;
72 kk++;
73 //cout<<aa[k].a<<endl;
74 break;
75 }
76 }
77 }
78 }
79 }
80 }
81 if (num==1)
82 {
83 cout<<"1 channel needed."<<endl;
84 }
85 else
86 {
87 cout<<num<<" channels needed."<<endl;
88 }
89 }
90 }
91 return 0;
92 }
View Code
hdu1175 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1175
注意记录转弯次数,判断是否在同一直线上,直接深搜即可
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3 int maze[1010][1010];
4 bool vis[1010][1010];
5 bool flage;
6 int dx[4]={0,0,1,-1};
7 int dy[4]={1,-1,0,0};
8 int n,m,q,x1,y1,x2,y2;
9 void dfs(int x,int y,int d,int t)
10 {
11 if (t>2||flage) return ;
12 if (t==2&&(x-x2)!=0&&(y-y2)!=0) return ;
13 if (x==x2&&y==y2&&t<=2)
14 {
15 flage=1;
16 return ;
17 }
18 for (int i = 0; i < 4; ++i)
19 {
20 int xx=x+dx[i];
21 int yy=y+dy[i];
22 if (xx<1||xx>n||yy<1||yy>m||vis[xx][yy]) continue;
23 if (maze[xx][yy]==0||(xx==x2&&yy==y2))
24 {
25 vis[xx][yy]=1;
26 if (d==-1||d==i) dfs(xx,yy,i,t);
27 else dfs(xx,yy,i,t+1);
28 vis[xx][yy]=0;
29 }
30 }
31 return ;
32 }
33 int main(int argc, char const *argv[])
34 {
35 while(cin>>n>>m)
36 {
37 if (n+m==0) break;
38 memset(maze,0,sizeof(maze));
39 for (int i = 1; i <= n; ++i)
40 {
41 for (int j = 1; j <= m; ++j)
42 {
43 cin>>maze[i][j];
44 }
45 }
46 cin>>q;
47 for (int i = 0; i < q; ++i)
48 {
49 cin>>x1>>y1>>x2>>y2;
50 memset(vis,0,sizeof(vis));
51 flage=0;
52 if (maze[x1][y1]==maze[x2][y2]&&maze[x1][y1])
53 {
54 dfs(x1,y1,-1,0);
55 }
56 if (flage) cout<<"YES"<<endl;
57 else cout<<"NO"<<endl;
58 }
59 }
60 return 0;
61 }
View Code
hdu5113 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5113
注意理解题目,已经输出行末不能有空格
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3 int visited[10][10];
4 int a[100];
5 int n,m,k;
6 bool flag=false;
7 void dfs(int x,int y,int nn)
8 {
9 for (int i = 1; i <= k; ++i)
10 {
11 if ((nn+1)<2*a[i]) return ;
12 }
13 if (nn==0)
14 {
15 flag=true;
16 return ;
17 }
18 else
19 {
20 for (int i = 1; i <= k; ++i)
21 {
22 if (visited[x-1][y]!=i&&visited[x][y-1]!=i&&a[i]!=0)
23 {
24 visited[x][y]=i;
25 a[i]--;
26 if (y==m) dfs(x+1,1,nn-1);
27 else dfs(x,y+1,nn-1);
28 if (flag) return ;
29 else
30 {
31 visited[x][y]=0;
32 a[i]++;
33 }
34 }
35
36 }
37 }
38 return ;
39 }
40 int main(int argc, char const *argv[])
41 {
42 int t;
43 cin>>t;
44 for (int kk = 1; kk <= t; ++kk)
45 {
46 flag=false;
47 memset(visited,0,sizeof(visited));
48 memset(a,0,sizeof(a));
49 cin>>n>>m>>k;
50 for (int i = 1; i <= k; ++i)
51 {
52 cin>>a[i];
53 }
54 dfs(1,1,n*m);
55 if(flag)
56 {
57 cout<<"Case #"<<kk<<":"<<endl;
58 cout<<"YES"<<endl;
59 for (int i = 1; i <= n; ++i)
60 {
61 for (int j = 1; j <= m; ++j)
62 {
63 if (j!=1) cout<<" ";
64 cout<<visited[i][j];
65 }
66 cout<<endl;
67 }
68 }
69 else
70 {
71 cout<<"Case #"<<kk<<":"<<endl;
72 cout<<"NO"<<endl;
73 }
74 }
75 return 0;
76 }
View Code
poj3134 题目链接:http://poj.org/problem?id=3134
(按书上写的)
1 #include <iostream>
2 //#include <stdlib.h>
3 using namespace std;
4 int val[1010];
5 int pos,n;
6 bool ida(int now,int depth)
7 {
8 if (now>depth) return false;
9 if (val[pos]<<(depth-now)<n) return false;
10 if (val[pos] == n) return true;
11 pos++;
12 for (int i = 0; i < pos; ++i)
13 {
14 val[pos] = val[pos-1] + val[i];
15 if (ida(now + 1,depth)) return true;
16 val[pos] = val[pos-1] - val[i];
17 if (ida(now + 1,depth)) return true;
18 }
19 pos --;
20 return false;
21 }
22 int main(int argc, char const *argv[])
23 {
24 int t;
25 while(cin>>n&&n)
26 {
27 int depth;
28 for (depth = 0; ; ++depth)
29 {
30 val[pos = 0] = 1;
31 if (ida(0,depth)) break;
32 }
33 cout<<depth<<endl;
34 }
35 return 0;
36 }
View Code