2015年第六届蓝桥杯 - 省赛 - C/C++大学A组 - G. 手链样式

手链样式

小明有3颗红珊瑚,4颗白珊瑚,5颗黄玛瑙。

他想用它们串成一圈作为手链,送给女朋友。

现在小明想知道:如果考虑手链可以随意转动或翻转,一共可以有多少不同的组合样式呢?

请你提交该整数。

不要填写任何多余的内容或说明性的文字。

Ideas

这是一个排列组合问题,一共有 12 个位置,可以先从中选出 3 个,放红珊瑚,然后从剩下的 9 个中选出 4 个放白珊瑚,剩余的 5 个位置放黄玛瑙。

这道题只是一道填空题,所以可以用一些语言自带的全排列函数,但是需要做一些去重的操作。

手链可以随意转动,相当于将排列进行右移操作,所以将上面的结果除以 12。

手链还能够翻转,也就是说必须保证对称轴两边的石头不同类型数量相等,所以必须由红珊瑚和黄玛瑙作为对称轴。

对称轴两边分别放 5 个石头,从 5 个位置里面选 2 个放白珊瑚,然后从剩下的 3 个位置中选 2 个放黄玛瑙。

考虑到翻转的情况,将上面的结果除以 2,然后再加上一个对称的操作。所以这道题其实是可以通过纯数学计算的方式得出结果的。

不过作为一名勤勤恳恳的码农,不写点代码总觉得难受,所以下面的代码是通过全排列+去重的方式实现的。

Code

C++

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>

using namespace std;

int main(int argc, const char *argv[]) {
    string s = "aaabbbbccccc";
    vector<string> v1;
    int ans = 0;
    do {
        //排出重复,对于v1中的每个元素进行检查,如果存在s的旋转或者翻转,则跳过
        int i = 0;
        for (; i < v1.size(); ++i) {
            if (v1[i].find(s) != string::npos)
                break;
        }
        //s不可用的情况
        if (i != v1.size())
            continue;
        string s2 = s + s;
        v1.push_back(s2);//用于判断旋转的情况
        reverse(s2.begin(), s2.end());
        v1.push_back(s2);//将s的翻转放入vector中

        ans++;
    } while (next_permutation(s.begin(), s.end()));
    cout << ans << endl;
    return 0;
}

Python

from itertools import permutations

if __name__ == '__main__':
    ans, cnt = set(), 0
    nums = ['1', '1', '1', '2', '2', '2', '2', '3', '3', '3', '3', '3']
    for item in permutations(nums):
        string = ''.join(item)
        if string not in ans:  # 如果这种样式之前已经遇到过
            print(string)
            string2 = string + string
            for i in range(len(nums)):
                ans.add(string2[i:i + 12])
            string2 = string2[::-1]  # 考虑翻转的情况
            for i in range(len(nums)):
                ans.add(string2[i:i + 12])
            cnt += 1
    print(cnt)

Answer: 1170

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大风车滴呀滴溜溜地转

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值