此题首先注意到最多不超过8个字符串,用全排列也只有2的8次方之多,所以首先可以确定是可以穷举,然后拼接完的字符串最长长度也不超过200,可以判断真的一直左移算法的循环次数也不会太大。所以这道题我采取的方式是穷举。以下是关键步骤的解析。
1 - 穷举产生全排列:
使用的方式是迭代,利用辅助vector<bool>判断该位置是否已使用,其次本意是想使用回溯的写的,奈何str字符串的回溯是有点麻烦,所以就直接传形参过去了。
2 - 题目的左移要求:
模运算就可以了,在generateK里面有具体步骤</bool>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// 3 - 完成题目的变态要求
int generateK(string &str)
{
int res = 0;
// 题目的特殊要求,左移相等的情况
for(int i=1; i<=str.size(); i++){ // 左移i次
bool flag = true;
for(int j=0; j<str.size(); j++){ // 判断每一次是否相同
if(str[j] != str[(j+i)%str.size()]){
flag = false;
break;
}
}
if(flag) res++;
}
#if 0
/* 测试代码段 */
cout<<"str:"<<str<<" res:"<<res<<endl;
#endif // 0
return res;
}
// 2 - 递归产生全排列
void generateRes(const int &K, int &res, vector<bool> &isUsed, const vector<string> &strs, string str, int count)
{
// 递归结束条件,产生一个全排列
if(count == strs.size()){
// 待实现
if( generateK(str) == K) res++;
return;
}
// 递归生成全排列
for(int i=0; i<strs.size(); i++){
if(isUsed[i]) continue; // 已经用过了
isUsed[i] = true;
generateRes(K, res, isUsed, strs, str+strs[i], count+1);
// 回溯
isUsed[i] = false;
}
return;
}
int main()
{
// 1 - 读入数据
int n, K;
cin>>n>>K;
vector<string> strs(n);
for(int i=0; i<n; i++) cin>>strs[i];
vector<bool> isUsed(n, false);
int res = 0;
// 2 - 递归产生全排列
string str = "";
generateRes(K, res, isUsed, strs, str, 0);
// 4 - 输出结果
cout<<res<<endl;
return 0;
}



京公网安备 11010502036488号