此题首先注意到最多不超过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; }