2015蓝桥杯C++A:手链样式

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


思路分析:
读题后会发现这是一个圆排列和环排列的问题。需要去除重复
这个题首先一定要理解题意,转动和翻转是个什么意思。

转动就是我们所得到的的排列是个环,即起点不固定,具体点说即使1234和2341是一种方式(3421也一样)。
在这里插入图片描述
s2是否是是s的旋转等价于s2是否是s+s的子串

翻转就是,这个排列是个立体的,可以上下左右翻转,具体点说即如图所示
在这里插入图片描述


代码:

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;

int main(){
string s="aaabbbbccccc";  //a,b,c分别指上面的三种样式
vector<string> v1;  //去重 
int ans=0;
do{
	//排除重复,对于v1中的每个元素进行检查,如果存在s的旋转或者转动,则跳过
	int i=0; //i定义在外面,若提前进行break,i一定不等于v1.size() 
	for(;i<v1.size();i++){  //需要一个栈 
		if(v1[i].find(s)!=string::npos) // v当中的旋转或翻转不是历史中的字符串
		//需要去和s中的字符串去比对 ,如果找到了,s不可用 
		break; //此break是上面for循环的结束 
	} 
	//s不可用的情况
	//反向考虑,如果s可用的话,上面的for()循环应该走完,最后一次
	//i++上来 ,i终止的状态就应该等于v1.size ,当提前终止就是下面的情况 
	if(i!=v1.size())
	continue;
	string s2=s+s;
	v1.push_back(s2);//用于判断旋转的情况
	reverse(s2.begin(),s2.end());  //
	v1.push_back(s2); //将s2的反转放入vector中
	ans++; 
} 
while(next_permutation(s.begin(),s.end()));  //s每次都是一个新的排列 
cout<<ans<<endl;
return 0;
}

在这里插入图片描述

发布了106 篇原创文章 · 获赞 5 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/gl620321/article/details/105082735