题目链接:力扣https://leetcode-cn.com/problems/maximum-score-words-formed-by-letters/
题意:
你将会得到一份单词表 words,一个字母表 letters (可能会有重复字母),以及每个字母对应的得分情况表 score。
请你帮忙计算玩家在单词拼写游戏中所能获得的「最高得分」:能够由 letters 里的字母拼写出的 任意 属于 words 单词子集中,分数最高的单词集合的得分。
单词拼写游戏的规则概述如下:
玩家需要用字母表 letters 里的字母来拼写单词表 words 中的单词。
可以只使用字母表 letters 中的部分字母,但是每个字母最多被使用一次。
单词表 words 中每个单词只能计分(使用)一次。
根据字母得分情况表score,字母 'a', 'b', 'c', ... , 'z' 对应的得分分别为 score[0], score[1], ..., score[25]。
本场游戏的「得分」是指:玩家所拼写出的单词集合里包含的所有字母的得分之和。
方法: 回溯法
class Solution {
private:
int size;
const int SIZE = 27;
vector<int> vct;//哈希表,用于记录小写字母出现的次数
vector<int> tmp;
vector<int> score;
vector<string> words;//存储单词
int maxS = 0;//最大的分
void backTrack(int index,int s)//i表示第几个单词,s表示得分
{
for(int i=index+1;i<size;i++)
{
if(!isValid(words[i])) continue;//字符串里的字符凑不齐就跳过
//凑齐了
int s1 = s;
vector<int> pre = tmp;
for(int j=0;j<26;j++)
{
s1 += score[j]*tmp[j];//更新得分
vct[j]-=tmp[j];//更新vct
}
maxS = max(maxS,s1);
backTrack(i,s1);//回溯
for(int j=0;j<26;j++)
{
vct[j]+=pre[j];//更新vct
}
}
}
bool isValid(string str)//判断字符串内的字符是否符合条件
{
tmp = vector<int>(SIZE,0);
for(auto& ch:str)
{
tmp[ch-'a']++;
}
for(int i=0;i<26;i++)
{
if(tmp[i]>vct[i]) return false;
}
return true;
}
public:
int maxScoreWords(vector<string>& words, vector<char>& letters, vector<int>& score) {
this->words = words;//将字符串集合变为全局
this->score = score;
vct = vector<int>(SIZE,0);
for(int i=0;i<letters.size();i++)//更新哈希表
{
vct[letters[i]-'a']++;//对应的字母数量自加
}
size = words.size();//统计单词数目
for(int i=0;i<size;i++)
{
if(!isValid(words[i])) continue;//字符串里的字符凑不齐就跳过
int s = 0;//统计得分
vector<int> pre = tmp;
//凑齐了
for(int j=0;j<26;j++)
{
s += score[j]*tmp[j];//更新得分
vct[j]-=tmp[j];//更新vct
}
maxS = max(maxS,s);//更新最大得分
backTrack(i,s);//回溯
for(int j=0;j<26;j++)
{
vct[j]+=pre[j];//更新vct
}
}
return maxS;//返回最大得分
}
};