• 元素的组合(dfs)


    无重复元素的组合

    输入一串小些字母(无重复字母),从中取出k(k<10)个字母,输出组合情况。
    样例:
    输入:
    abcd
    3
    输出:
    abc
    abd
    acd
    bcd

    一道搜索的题,想办法建图或是画搜索树。

    这里推荐建图的方法,因为是组合情况,不用考虑顺序,也就是说,元素一样,顺序不一样算同一种组合。

    那么为了避免重复组合,就应该规定一个组合顺序,比如ASCII值从小到大。

    那么这道题的图就是一个有向图的遍历了。

    从每一个结点开始遍历,累计遍历到结点数等于k时,输出。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 using namespace std;
     7 #define rep(i, a, n) for(int i = a; i <= n; ++i) 
     8 #define per(i, n, a) for(int i = n; i >= a; --i)
     9 typedef long long ll;
    10 int len, k, tot = 0;
    11 char a[15], ans[15];
    12 int vis[500];
    13 void print(int tot)
    14 {
    15     rep(i, 1, k) printf("%c", ans[i]); printf("
    ");
    16 }
    17 void solve(char id, int step)
    18 {
    19      if(step == k + 1) print(++tot); 
    20     for(int i = id; i <= 'z'; ++i)    //从这个结点的ASCII值开始,尝试走到所有比他大的结点 
    21     {
    22         if(vis[i])        //结点存在 
    23         {    
    24             ans[step] = i; vis[i] = 0; 
    25             solve(i, step + 1);        
    26             vis[i] = 1;
    27         }
    28     }
    29 }
    30 
    31 int main()
    32 {
    33 //    freopen("p4.in", "r", stdin);
    34 //    freopen("p4.out", "w", stdout);
    35     scanf("%s%d", a, &k);
    36     len = strlen(a);
    37     sort(a, a + len);
    38     rep(i, 0, len - 1) vis[a[i]] = 1;
    39     solve('a', 1);    
    40     return 0;
    41 }

    有重复元素的组合

    输入一串小些字母(有重复字母),从中取出k 个字母,输出组合情况。
    样例:
    输入:
    aabbcc
    4
    输出:
    1:aabb
    2:aabc
    3:aacc
    4:abbc
    5:abcc
    6:bbcc

    这下元素有重复了,若还是按上述方式建图

    会发现,从结点a有三条出边b(左下),b(右下),c。而从左下角的b走到c,和从右下角的b走到c得到的组合相同。所以对于每一个结点的出边指向的结点,其种类应该是两两不相同的,也就是说,图应该改为这样

    然后遍历所有点就行了。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 using namespace std;
     7 #define rep(i, a, n) for(int i = a; i <= n; ++i) 
     8 #define per(i, n, a) for(int i = n; i >= a; --i)
     9 typedef long long ll;
    10 int len, k, tot = 0;
    11 char a[15], ans[15];
    12 int vis[500];
    13 void print(int tot)
    14 {
    15     printf("%d:", tot);
    16     rep(i, 1, k) printf("%c", ans[i]); printf("
    ");
    17 }
    18 void solve(char id, int step)
    19 {
    20      if(step == k + 1) print(++tot); 
    21     for(int i = id; i <= 'z'; ++i)
    22     {
    23         if(vis[i])
    24         {    
    25             ans[step] = i; vis[i]--;     //该点走过了 
    26             solve(i, step + 1);        
    27             vis[i]++;
    28         }
    29     }
    30 }
    31 
    32 int main()
    33 {
    34 //    freopen("p5.in", "r", stdin);
    35 //    freopen("p5.out", "w", stdout);
    36     scanf("%s%d", a, &k);
    37     len = strlen(a);
    38     sort(a, a + len);
    39     rep(i, 0, len - 1) vis[a[i]]++;
    40     solve('a', 1);    
    41     return 0;
    42 }
  • 相关阅读:
    可汗学院的数学从零开始学习顺序?
    判断两个数组内容是否相同
    eclipse package,source folder,folder区别及相互转换
    [垂直化搜索引擎]lucene简介及使用
    有效处理Java异常三原则
    ZeroMQ作者于昨天下午宣布选择安乐死
    linux一路填坑...
    gcc/g++/makefile/easymake/cmake/xmake/nmake ...
    RTSP客户端接收存储数据(live555库中的openRTSP实例)
    RTSP客户端接收存储数据(live555库中的testRTSPClient实例)
  • 原文地址:https://www.cnblogs.com/mrclr/p/8635956.html
Copyright © 2020-2023  润新知