博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
7.29 DFS总结
阅读量:5292 次
发布时间:2019-06-14

本文共 7086 字,大约阅读时间需要 23 分钟。

7.29   黄昏时刻

 

 

(一) 全排列

 

建模:

  给了数字n 代表从1-n 个数全排列

 

思路:

  1. 输入n,如果n值为‘0’,则退出程序

  2. vis[i] 保存 是否对第i个数字进行访问
  3. dfs 遍历1-n 个数字的全排列,若重复访问,则越过。直到最终访问结束输出访问的的结果。之后回溯删掉对数字的访问。

优化:

  none

 

代码:

1 #include 
2 #include
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 
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 
2 #include
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
max) //更新当前搜索到的最长路径43 max=sum;44 for(i=0;i

 

 

(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 
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 
2 #include
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 
2 #include
3 #include
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

 

1 // The Settlers of Catan V2 2  3 void dfs(int u, int num){ 4   int flag; 5     for(int v=0; v
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

 

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

 

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 }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/firstrate/p/3223105.html

你可能感兴趣的文章
为什么要用日志框架 Logback 基本使用
查看>>
实用Android开发工具和资源精选
查看>>
TileMap
查看>>
JS属性大全
查看>>
java复制文件
查看>>
第一册:lesson seventy nine.
查看>>
GCD的同步异步串行并行、NSOperation和NSOperationQueue一级用dispatch_once实现单例
查看>>
团队作业
查看>>
数据持久化时的小bug
查看>>
mysql中key 、primary key 、unique key 与index区别
查看>>
bzoj2257
查看>>
Linux查看文件编码格式及文件编码转换<转>
查看>>
Leetcode: Find Leaves of Binary Tree
查看>>
Vue 模板解释
查看>>
http://www.bootcss.com/
查看>>
20145308 《网络对抗》 注入shellcode+Return-to-libc攻击 学习总结
查看>>
将多张图片和文字合成一张图片
查看>>
自己动手写ORM(01):解析表达式树生成Sql碎片
查看>>
如何使用USBWebserver在本机快速建立网站测试环境
查看>>
百度Ueditor编辑器的Html模式自动替换样式的解决方法
查看>>