题目描述 小明有3颗红珊瑚,4颗白珊瑚,5颗黄玛瑙。 他想用它们串成一圈作为手链,送给女朋友。 现在小明想知道:如果考虑手链可以随意转动或翻转,一共有多少不同的组合样式?
输出 请你输出该整数。不要输出任何多余的内容或说明性的文字。
首先一定要理解题意 转动和翻转是个什么意思,转动就是我们所得到的的排列是个环,即起点不固定,具体点说即使1234和2341是一种方式(3421也一样)。翻转就是,这个排列是个立体的,可以上下左右翻转 即 如何判断是否串是已经出现过的情况比较难想,下面提供一种思路 判断转动情况是否存在,可把字符串复制一份,查看其子串里是否含有某种字符串 如abcabc变为abcabcabcabc存起来 当要判断cabcab是否存在时,只需判断cabcab是否是abcabcabcabc的子串。 翻转用reverse函数翻转,再查看是否存在 注意翻转和转动可能同时存在,所以要把翻转传也要复制一份存起来。 注意翻转字符串一定不能直接翻转当前的串,因为当前传要完成全排列来模拟所有的情况,一旦翻转了串会认为已经变化了。所以翻转要翻转与其值相同的另外的串。 判断当前字符串是否已经存在使用的是vector,在每次插入新字符串之前要查重判断。判断函数 if(v[i].find(s) != string::npos) string::npos如果作为一个返回值(return value)表示没有找到匹配项。 详细用法见string::npos的一些说明 代码如下
#include <iostream> #include<queue> #include<cstring> #include<algorithm> #include<cstdio> #include<math.h> #include<cmath> #include<string> using namespace std; int main() { string s = "aaabbbbccccc";//模拟345三种宝石串 vector<string>v; int ans = 0; int quitflag; do { quitflag = 1; for(int i=0;i<v.size();i++) { if(v[i].find(s) != string::npos) //没到最后就找到了,说明有重复 { quitflag = 0; break; } } if(quitflag == 0) continue;//如果找到重复的就跳过本次循环 string s2 = s+s; v.push_back(s2);//两串相加用来判断转动 reverse(s2.begin(),s2.end());//翻转 v.push_back(s2);//翻转用来判断串翻转后相等的情况 ans++; }while(next_permutation(s.begin(),s.end()));//全排列找出所有串的组合情况 cout<<ans; }