题解 | #魔法权值#

魔法权值

http://www.nowcoder.com/questionTerminal/8c759758b2e746a18a31b4eee5d4000b

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

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务