A A 2 2 3 3 4 4, 一共4对扑克牌。请你把它们排成一行。
要求:两个A中间有1张牌,两个2之间有2张牌,两个3之间有3张牌,两个4之间有4张牌。请填写出所有符合要求的排列中,字典序最小的那个。
例如:22AA3344 比 A2A23344 字典序小。当然,它们都不是满足要求的答案。
请通过浏览器提交答案。“A”一定不要用小写字母a,也不要用“1”代替。字符间一定不要留空格。
分析:
这道题若果直接顺着题的思路,先排列A,隔一张排列另一个A;再排列2,隔两张排列另一个2……这样实现起来会非常麻烦。我们可以逆向思考,先把八张扑克牌全排列,然后从中找到符合标准的序列放在vector中,标准是:两个A的下标差为2,两个2的下表差为3……再把vector中的元素排序,序列首端就是字典序最小的那个。
关于全排列函数next_permutaitin,上一篇文章已将讲过,不再赘述。
注意:
1.初始序列要是最小序列,这样使用next_permutaition才能得到全排列。最小序列根据ASCII码规定,'0'-'9':48-57;'A'-'Z':65-90;'a'-'z':97-122;所以最小序列是:223344AA。
2.返回字符串中某个字符的地址,可采用find函数。find()常用的形式有两种:
(1)string::find(char ch)
若找到,返回ch在string中的第一个位置;
若没有找到,则返回string::npos,是一个大于字符串长度的值,一般取值为4294967295。
(2)string::find(char ch,size_type index)
从index位置开始查找ch,返回结果同上。
代码:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main(void) {
vector<string> v;
string s = "223344AA";
do {
unsigned beginA = s.find("A", 0);//unsigned int 直接简写为 unsigned
unsigned endA = s.find("A", beginA + 1);//在s中查找A,查找起始点为beginA的下一个地址,返回找到的A的位置
unsigned begin2 = s.find("2", 0);
unsigned end2 = s.find("2", begin2 + 1);
unsigned begin3 = s.find("3", 0);
unsigned end3 = s.find("3", begin3 + 1);
unsigned begin4 = s.find("4", 0);
unsigned end4 = s.find("4", begin4+ 1);
if(endA - beginA== 2 && end2 - begin2 == 3 && end3 - begin3 == 4 && end4 - begin4 == 5) {
v.push_back(s);
}
} while(next_permutation(s.begin(), s.end()));
sort(v.begin(),v.end());
cout<<(*v.begin());//数组字典序列最小的那个字符串
}
结果: