7.29 DFS总结
来源:互联网 发布:数据库验收要求 编辑:程序博客网 时间:2024/05/21 18:33
7.29 黄昏时刻
(一) 全排列
建模:
给了数字n 代表从1-n 个数全排列
思路:
1. 输入n,如果n值为‘0’,则退出程序
2. vis[i] 保存 是否对第i个数字进行访问
3. dfs 遍历1-n 个数字的全排列,若重复访问,则越过。直到最终访问结束输出访问的的结果。之后回溯删掉对数字的访问。
优化:
none
代码:
1 #include <stdio.h> 2 #include <string.h> 3 4 int a[20] ,n, vis[20]; 5 6 void dfs(int s) { 7 int i; 8 //如果dfs 次数为n,则输出a数组的内容 9 if(s == n) {10 for(i = 0; i < n; i++)11 printf("%-5d", a[i]); // -5 是格式化输出左对齐12 printf("\n");13 return;14 }15 //遍历 1- n 如果访问过则继续循环呗16 for(i = 1; i <= n; i++) {17 18 if(vis[i]) continue;19 vis[i] = 1; //标记节点被访问过20 a[s] = i; //在a 数组存取全排列的数字21 dfs(s+1); //深搜22 vis[i] = 0; //回溯操作,删掉节点访问痕迹23 }24 }25 26 27 int main() {28 while(1) {29 scanf("%d", &n);30 if(!n) break;31 memset(vis, 0, sizeof(vis));32 dfs(0);33 }34 return 0;35 }
(二)全组合
建模:
给了数值n 对n 进行组合,并打印出。
思路:
1.输入n , 如果n不存在 返回。
2.dfs 找出n个数字的组合,用‘0’,‘1’标记法判断一个数字是否存在,并且对存在或者不存在依次进行递归。
3.若dfs次数>n,则输出组合的结果。
代码:
1 #include <stdio.h> 2 3 int n, a[20]; 4 5 void dfs(int s) { 6 int i; 7 //输出排列后的结果 8 if(s > n) { 9 for(i = 1; i <= n; i++) {10 if(a[i]) 11 printf("%-5d ", i); 12 }13 return;14 }15 //对a[s]的存在亦或是不存在的两种情况进行递归。16 a[s] = 0;17 dfs(s+1);18 a[s] = 1;19 dfs(s+1);20 }21 22 int main() {23 24 while(1) {25 scanf("%d", &n);26 if(!n) break;27 dfs(1);28 }29 30 return 0;31 }
(D89) The settlers of catan
建模:
已知n 个点,m 条边,输入两个点来构成一条边,构成一副无向图,两点之间可以有多条边,从任意一个点搜索,要求每条边只能经过一次,找到最长的路径。
思路:
1.输入点的个数n, 边的个数m,并且初始化存整个无向图的二维数组w
2.存边进入二维数组W
3.对所有点进行dfs搜索,如果路径最长则更新max
4.dfs找出所有存在的边,并且记录路径的长度
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #define N 26 4 5 int w[N][N],max,n; //w[N][N] 存入整个图,w[i][j]=x 代表i到j有x条边 6 7 void dfs(int,int); 8 9 int main()10 {11 int m,sum;12 int a,b,i;13 while(1)14 { 15 scanf("%d%d",&n,&m);16 if(!m && !n)17 break;18 19 memset(w,0,sizeof(w)); //初始化20 21 for(i=0;i<m;i++)22 {23 scanf("%d%d",&a,&b);24 w[a][b]++; //无向图25 w[b][a]++;26 }27 28 max=0; 29 for(i=0;i<n;i++)30 {31 sum=0; //把每个点作为出发点,对每一个点进行搜索32 dfs(i,sum);33 }34 printf("%d\n",max);35 }36 return 0;37 }38 39 void dfs(int a,int sum) // a 为当前探索到哪一个节点,sum为当前探索到的路径长度40 {41 int i;42 if(sum>max) //更新当前搜索到的最长路径43 max=sum;44 for(i=0;i<n;i++)45 {46 if(w[a][i])47 {48 w[a][i]--; w[i][a]--; //用去一条边49 dfs(i,sum+1); // 进行下一层递归50 w[a][i]++; w[i][a]++; //回溯到上一层51 52 }53 }54 return;55 }
(A38) A long stick
建模:
给了n个棍子的长度, 和b的值
找出一些棍子链接起来得到长度length, length >= b, length尽量接近b
思路:
1. min为结果, 初始化为所有棍子的长度和。
2. dfs找出这堆棍子的组合, 判断每一种组合所得到的长度sum, sum与min相比, 如果sum比min更优, 更新min为sum
优化:
1. 剪枝
a)在当前搜索到的状态下, 假设剩下的棍子全部装完, 得到的结果 < b, 则可以剪枝.
b)当搜索到的sum >= b时, 判断sum 与 min, 然后剪枝
2. 排序, 将棍子长度逆序排序, 在搜索的过程中, sum的增长速度会更快, 也可以提高剪枝效率。
未优化的代码:
1 #include <stdio.h> 2 3 int n, b; 4 int len[28]; 5 int min; 6 7 void dfs(int ,int); 8 9 int main() {10 int t, i;11 scanf("%d", &t);//输入t次后结束12 while(t--) {13 14 scanf("%d%d", &n, &b);//n为小棍子数目,b为拼接后的长度最接近的值15 min = 0;//拼接后趋近的结果16 for(i = 0; i < n; i++) {//输入n组小棍子长度17 scanf("%d", &len[i]);18 min += len[i];19 }20 21 dfs(0,0);//递归求最接近b长度的若干根棍子合起来的长度值22 printf("%d\n", min);//输出结果23 }24 25 return 0;26 }27 28 void dfs(int sum, int i) {29 30 if(min == b) //假如拼接后的长度min 刚好为b 则返回31 return;32 if(sum >= b) {//如果棍子拼接的长度刚好>=b 如果比之前拼接的长度更接近于b,就更新min33 if(sum < min) 34 min = sum;35 return;36 }37 if(i == n) return;//避免死递归判断假如存在n的情况38 dfs(sum+len[i], i+1);//如果存在第i根棍子,往下搜索求和39 dfs(sum, i+1);//假设不存在第i根棍子,继续搜索求和40 }
剪枝后的优化:
1 #include <stdio.h> 2 #include <string.h> 3 4 int n, b; 5 int len[28], s[28]; 6 int min; 7 8 void dfs(int sum, int i); 9 10 int main() {11 int t, i;12 scanf("%d", &t);13 while(t--) {14 15 scanf("%d%d", &n, &b);16 min = 0;17 memset(s, 0, sizeof(s));18 for(i = 0; i < n; i++) {19 scanf("%d", &len[i]);20 min += len[i];21 }22 for(i = n-1; i > -1; i--) //记录最后一根棍子 to 第i根棍子 的总长度23 s[i] = s[i+1] + len[i];24 25 dfs(0,0);26 printf("%d\n", min);27 }28 return 0;29 }30 31 void dfs(int sum, int i) {32 if(min == b) 33 return;34 if(sum >= b) {35 if(sum < min) 36 min = sum;37 return;38 }39 if(i == n) return;40 if(sum+len[i]+s[i+1] >= b ) //剪枝 41 dfs(sum+len[i], i+1);42 if(sum+s[i+1] >= b) //剪枝43 dfs(sum, i+1);44 45 }
剪枝排序后的优化:
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 5 int n, b; 6 int len[28], s[28]; 7 int min; 8 9 void dfs(int sum, int i);10 11 int cmp(const void *a,const void *b)12 {13 return *(int *)b-*(int*)a;14 }15 16 17 18 int main() {19 int t, i;20 scanf("%d", &t);21 while(t--) {22 23 scanf("%d%d", &n, &b);24 min = 0;25 memset(s, 0, sizeof(s));26 for(i = 0; i < n; i++) {27 scanf("%d", &len[i]);28 min += len[i];29 }30 31 qsort(len,n,sizeof(len[0]),cmp);32 33 34 for(i = n-1; i > -1; i--) //记录最后一根棍子 to 第i根棍子 的总长度35 s[i] = s[i+1] + len[i];36 37 dfs(0,0);38 printf("%d\n", min);39 }40 return 0;41 }42 43 void dfs(int sum, int i) {44 if(min == b) 45 return;46 if(sum >= b) {47 if(sum < min) 48 min = sum;49 return;50 }51 if(i == n) return;52 if(sum+len[i]+s[i+1] >= b ) //剪枝 53 dfs(sum+len[i], i+1);54 if(sum+s[i+1] >= b) //剪枝55 dfs(sum, i+1);56 57 }
DFS 题目 用到的DFS函数:
1 // The Settlers of Catan V1 2 3 void dfs(int a,int sum) 4 { 5 int i; 6 if(sum>max) max=sum; 7 for(i=0;i<n;i++) 8 9 if(w[a][i]){10 w[a][i]--; w[i][a]--; 11 dfs(i,sum+1); 12 w[a][i]++; w[i][a]++; 13 }14 15 return;16 }
1 // The Settlers of Catan V2 2 3 void dfs(int u, int num){ 4 int flag; 5 for(int v=0; v<n; ++v){ 6 if(G[u][v] && !vis[u][v]){ 7 8 if(G[u][v] != 1){ 9 flag = 1;10 vis[u][v] = 0;11 vis[u][v] = 0;12 G[u][v] --; 13 G[v][u] --;14 }15 else {16 vis[u][v] = 1;17 vis[v][u] = 1;18 19 }20 21 dfs(v, num+1);22 if(flag == 1){23 G[u][v]++;24 G[v][u]++;25 }26 flag = 0;27 vis[u][v] = vis[v][u] = 0;28 }29 }30 31 if(num > maxNum) maxNum = num;32 }
1 // A long stick 2 3 void dfs(int sum,int i) 4 { 5 int j; 6 sum-=stick[i]; 7 if(sum<length || min==length) 8 return; 9 10 if(sum<min)11 min=sum;12 13 for(j=i+1;j<=n;j++)14 dfs(sum,j);15 }
1 // repeatless V1 2 3 void dfs(int dep) 4 { 5 int i; 6 if (dep==10) 7 { 8 int tmp=d[1]; 9 for (i=2;i<=10;i++) tmp=tmp*10+d[i];10 T++;11 f[T]=tmp;12 return;13 }14 if (T>1000010) return;15 for (i=0;i<=9;i++)16 if (s[i]==0)17 {18 d[dep+1]=i;19 sum+=i;20 if (sum) s[i]++;21 dfs(dep+1);22 if (sum) s[i]--;23 sum-=i;24 }25 }
1 // repeatless V2 author : ZSX 2 3 void recursion( int k ) 4 { 5 if( bl == 0 ) 6 return ; 7 int i, j; 8 int a, b; 9 if( p == k )10 {11 int sum = 0;12 int temp;13 for( i=0; i<p; i++ )14 {15 temp = 1;16 for( j=0; j<p-i-1; j++ )17 temp *= 10;18 sum += temp*buffer[i];19 }20 if( q <= 1000000)21 array[q++] = sum;22 else 23 bl = 0;24 }25 else26 {27 for( a=0; a<=9; a++ )28 if( flag[a] == 0 && (p != 0 || a!=0) )29 {30 flag[a] = 1;31 buffer[p++] = a;32 recursion( k );33 flag[a] = 0;34 p--;35 }36 }37 }
1 // 全排列 2 3 void dfs(int s, int n) { 4 int i; 5 if(s == n) { 6 for(i = 0; i < n; i++) 7 if(i==0) printf("%d", a[i]); 8 else printf(" %d", a[i]); 9 printf("\n");10 return;11 }12 for(i = 1; i <= n; i++) {13 if(vis[i]) continue;14 a[s] = i;15 vis[i] = 1;16 dfs(s+1, n);17 vis[i] = 0;18 }19 }
- 7.29 DFS总结
- dfs总结
- DFS 总结
- dfs总结
- dfs总结
- DFS总结
- DFS,BFS算法总结
- dfs学习总结
- BFS与DFS总结
- 总结之bfs,dfs
- dfs简单总结
- Dijkstra+DFS模板总结
- DFS学习归纳总结
- DFS序总结
- DFS BFS 搜索总结
- DFS-lintcode解法总结
- DFS个人总结
- 数据结构总结之dfs
- 7.24 快排总结
- 7.24 小结
- 7.25 RPN转换
- SZU:B47 Big Integer I
- SZU:D89 The Settlers of Catan
- 7.29 DFS总结
- 算法:优先级队列
- 最短路径 dijkstra
- FLOYD 求最小环
- Vijos: P1046观光旅游
- Linux系统编程:dup2()重定向
- Linux系统编程:客户端-服务器用FIFO进行通信
- Linux : fedora 安装 vnc server
- C程序设计语言(第二版)习题:第一章