手链样式

参考博客原址:https://blog.csdn.net/jinglelia/article/details/79344537

小明有3颗红珊瑚,4颗白珊瑚,5颗黄玛瑙。
他想用它们串成一圈作为手链,送给女朋友。
现在小明想知道:如果考虑手链可以随意转动或翻转,一共可以有多少不同的组合样式呢?

分析:这个题首先一定要理解题意,转动和翻转是个什么意思,转动就是我们所得到的的排列是个环,即起点不固定,具体点说即使1234和2341是一种方式(3421也一样)。翻转就是,这个排列是个立体的,可以上下左右翻转, 具体点说即
  1             1

2   3  和  3   2 是一样的(左右翻转),弄清了题意,就能事半功倍。
   4            4
方法一:利用数学的排列组合进行求解,首先我们科普一个小的知识,见图:

意思很明白了,这个题,我们就是先C(12,3)选出红珊瑚的位置,在 C(9,5)选出黄马瑙的位置,这就是总的情况了,由于是环排列,我们将结果除以12,得到不考虑翻转的情况,然后再考虑翻转的时候要考虑到对称的情形,这种翻转是没有影响的,
对称即   

               A
         A         A
         B         B
         B         B
         C         C
         C         C
              C
这种类型,这种情形的一共有C(5,2)*C(3,2) = 30种(只看一侧的),那么结果即:(2310-30)/2+30 = 1170;(立体排列除以2)

方法二:暴力枚举,我们直接把每一次得到的串先复制拼接一下(模拟旋转)成环,再翻转一下,如果两次得到的串在已得的串里面没有就加入,直接看代码吧,挺清楚的,鉴于c++里面有直接全排列去重的方法,那么我借鉴了,Java没有啊,直接写很麻烦。。。。


   
   
  1. #include <iostream>
  2. #include <algorithm>
  3. #include <string>
  4. #include <vector>
  5. using namespace std;
  6. vector< string> v; //存储已经找出的情况
  7. int sum = 0;
  8. int main(){
  9. string str = "aaabbbbccccc";
  10. do{
  11. vector< string>::iterator it;
  12. for(it=v.begin(); it != v.end(); it++){
  13. if((*it).find(str, 0) != string::npos){ //如果在已得的里面能找到,就判断下一个
  14. break;
  15. }
  16. }
  17. if( it != v.end() ) continue;
  18. string str2 = str + str;
  19. v.push_back(str2);
  20. reverse(str2.begin(), str2.end()); //需要algorithm头文件
  21. v.push_back(str2);
  22. sum ++;
  23. } while(next_permutation(str.begin(), str.end()));
  24. cout << sum ;
  25. }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值