手链样式

来源:互联网 发布:1737棋牌源码 编辑:程序博客网 时间:2024/06/10 04:33

手链样式

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

请你提交该整数。不要填写任何多余的内容或说明性的文字。

本文地址:http://blog.csdn.net/u013619254/article/details/50910788

这是2015年蓝桥杯省赛C++A组里面的一道题目,题目有点难理解,但搞清楚题意之后还是不难解决的。由于网上有几个版本的答案,而且都不对,所以现附上官方的答案:

(这是本人的老师参加蓝桥在厦大开的培训拿回来的资料):


首先来分析一下题目:3类珠子,一共12个,我们用字符串a="333444455555“表示,要求环形的排列数,注意理解可以随意转动或翻转,这跟直线型的有不同。举个例子:

例如,在直线型排列中a="333444455555“ b="444455555333“ 是不同的排列,原因是直线型的起点是固定的,对应位置元素只要有一个不同,则排列不同。但是在环形里面,由于可以任意转动,也就是起点不固定的,当b以第一个3为起点时往右数时,它就和a完全一样了。另外,任意翻转的意思是b不但起点不固定,而且排列的方向可以往右数,也可以往左数。

因此,最暴力的解法来了:

1、用一个容器V保存不同样式的排列,首先将第一种排列保存起来,假设就保存a="333444455555“吧。

2、然后我们对"333444455555“进行全排列(排列的方法很关键等下会讲),每取出一个排列t,就和容器V里面的所有的样式Vi比较,比较方法:将两个t连在一起,形成tt,用C函数strstr判断Vi是否是tt的子字符串,如果是,则取下一个排列t1。反之,将tt翻转为tt‘,再用strstr判断Vi是否是tt ’的子字符串,如果不是,则t是一个新的样式,这时将t加入容器V中。


到此已经有解决问题的方法了,问题是如果采用纯递归的全排列方式,运行时间很久,具体多久我也不知道,反正我去饭堂吃了一顿饭回来还没运行出来。

12个数的全排列很大,但是我们应该注意到a="333444455555“有很多元素重复的,所以我们对其取全排列时应该去重,举个例子,122的全排列是122,122,221,221,212,212,,去重之后是122 ,212,221。要求去重全排列,可以自己在递归的基础上改,但是我们不用那么麻烦,直接调用函数next_permutation(A,A+size)就行了。该函数具体用法自行百度吧。注意的是需要将初始序列写成"333444455555“。

好了,说了那么多,还是直接上代码吧。如有问题,尽管提出。


 #include <iostream>#include <stdlib.h>#include <math.h>#include <string.h>#include <fstream>#include <algorithm>#include <vector>#include <time.h>using namespace std;vector <string> C;//用一个vector保存已经产生的不同的样式 int num=1;int main(){//ifstream cin ("test.txt");clock_t s,f;s=clock();char c[13]="333444455555";C.push_back(c);//这肯定是一种排列 cout<<C[0];do{char tt[25],ttr[25];strcpy(tt,c);//将一个c复制出来 strcat(tt,c);//tt是两个c连在一起 strcpy(ttr,tt);//备份一个ttr strrev(ttr);//翻转ttrchar t1[13];int f=1;//cout<<tt<<"  "<<ttr<<" "<<c<<endl;for(int j=0;j<num;j++){//遍历保存好的样式C for(int k=0;k<=12;k++){//for的目的是将C中的一个元素赋给t1,这样做的目的是因为直接用C[j],strstr函数用不了(⊙﹏⊙)b t1[k]=C[j][k];}//cout<<t1<<endl;if(strstr(tt,t1)||strstr(ttr,t1)){ f=0;break;//有重复的则退出遍历C }}if(f) {//没有有重复的 num++;C.push_back(c);//将这个不同的排列加到C中 cout<<c<<" "<<num<<endl;}}while(next_permutation(c,c+12));//调用stl里面的全排列函数,不要自己写递归全排列,因为本身要排列的序列有很多个元素相同的,会多很多无谓的尝试,浪费时间 f=clock();cout<<endl<<"time  "<<(f-s)/CLOCKS_PER_SEC<<endl;return 0;}







2 0
原创粉丝点击