zoukankan      html  css  js  c++  java
  • 【9501】有重复元素的排列问题

    Time Limit: 10 second
    Memory Limit: 2 MB

    问题描述
    设r={r1,r2,...,rn}是要进行排列的n个元素,其中r1,r2,...,rn可能相同。给定 n以及待排列的n个元素,设计一个算法,求出这n个元素的所有不同排列。

    Input

    第一行是元素个数n,1≤n≤500,接下来第二行起(即有可能不同行)是待排列的n个元素。

    Output

    n个元素的所有不同排列(按字典顺序依次输出),最后一行中的数是排列总数

    Sample Input

    4
    aacc
    

    Sample Output

    aacc
    acac
    acca
    caac
    caca
    ccaa
    6
    

    Sample Input1

    16
    cccc
    cccc
    cccc
    cccc
    

    Sample Output1

    cccccccccccccccc
    1
    

    【题解】

    首先把字符读入,要用( while cin >> str != eof ),这样可以一直读到文件结束。

    读完之后将读入的东西村在字符串中,扫描一下各个字母出现的次数,用a[1..26]来代表26个字母出现的个数。

    搜索的策略是,for i =1 to 26 ,如果a[i] > 0,则用i这个字母来进行组合。

    如aacc;

    a[1] = 2;a[3] =2;

    先是看到a[1]  > 0,先用掉一个当前字符串变成“a”,然后让a[1]递减。

    再扫描的时候又看到了a[1] == 1 >0,再用a,然后字符串变成"aa",这时候a[1] 变成0了,

    再扫描 遇到a[3] >0,再加一个c进去,字符串变成“aac”,a[3]--,再扫描,仍然是a[3]>0,再用一次,a[3]==0,这时字符串变成“aacc”,输出。

    然后搜索退一层,a[3] == 1,但是没有i > 3的a[i]满足a[i] >0 了,于是再退一层,a[3] == 2,这时字符串已经变成又变回“aa”了,这时的i刚搜完3,而a[4..26]没有大于0 的,

    于是再退一层,字符串变成“a”这时a[1] = 1,a[3] =2,我们的i ==1 ,这时候 i再变成3,遇到a[3] == 2,加上一个c,字符串变成“ac”。。。。

    以此类推。

    可以看到,这样的搜索策略不会出现重复的情况,省去了判重的工作。

    这个道题主要就是考的搜索策略。

    【代码】

    #include <cstdio>
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    int n,num = 0,l,now = 0,a[27],ans[550],ta = 0;
    string s,ts;
    bool bo[550];
    
    void input_data() //输入数据
    {
        scanf("%d",&n);
        s= "";
        while ( ( cin >> ts)) //用于输入不定行的字符串
            s += ts; //把它们连接起来
        l = s.size();//获取字符串的长度
        for (int i = 1;i <= 26;i++)
            a[i] = 0;
        for (int i = 0;i <= l-1;i++) //统计各个字母出现的次数。
            a[s[i]-'a'+1]++;
    }
    
    void sear_ch(int d)
    {
        ans[++now] = d; //记录下我们用的字母是什么 以int的形式存储
        a[d]--; //用掉了 就要递减。
        for (int i = 1;i <= 26;i++) //查找剩余的可用字母
            if (a[i] > 0)
                sear_ch(i);
        if (now == l) //如果所有字母都用过了,就输出。
            {
                for (int i = 1;i <= now;i++)
                    putchar(ans[i]-1 +'a');
                printf("
    ");
                ta++; //方案数递增。
            }
        now--; //回溯。
        a[d]++;
    }
    
    void get_ans()
    {
        for (int i = 1;i <= 26;i++) //如果某个字母还有剩余,就用它。
            if (a[i] > 0)
                sear_ch(i);
    }
    
    void output_ans()
    {
        printf("%d
    ",ta);
    }
    
    int main()
    {
        //freopen("F:\rush.txt","r",stdin);
        input_data();
        get_ans();
        output_ans();
        return 0;
    }
    
  • 相关阅读:
    [友谊篇FRIENDSHIP]Learn with whole Life 一生的学习
    IIS还原备份xml配置文件
    从A到Z的人生名言
    爱情六十九课,节制抱怨
    C# list 去重复
    win7 iis7.5 下配置MVC3问题
    Kill oracle session
    Windows7删除文件提示"您需要权限来执行此操作"没有权限无法删除文件的解决方法
    json对象
    js的属性和方法的类型
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632443.html
Copyright © 2011-2022 走看看