【回溯】1255. 得分最高的单词集合

本文涉及知识点

回溯
力扣难道:1881

LeetCode1255. 得分最高的单词集合

你将会得到一份单词表 words,一个字母表 letters (可能会有重复字母),以及每个字母对应的得分情况表 score。
请你帮忙计算玩家在单词拼写游戏中所能获得的「最高得分」:能够由 letters 里的字母拼写出的 任意 属于 words 单词子集中,分数最高的单词集合的得分。
单词拼写游戏的规则概述如下:
玩家需要用字母表 letters 里的字母来拼写单词表 words 中的单词。
可以只使用字母表 letters 中的部分字母,但是每个字母最多被使用一次。
单词表 words 中每个单词只能计分(使用)一次。
根据字母得分情况表score,字母 ‘a’, ‘b’, ‘c’, … , ‘z’ 对应的得分分别为 score[0], score[1], …, score[25]。
本场游戏的「得分」是指:玩家所拼写出的单词集合里包含的所有字母的得分之和。
示例 1:
输入:words = [“dog”,“cat”,“dad”,“good”], letters = [“a”,“a”,“c”,“d”,“d”,“d”,“g”,“o”,“o”], score = [1,0,9,5,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0]
输出:23
解释:
字母得分为 a=1, c=9, d=5, g=3, o=2
使用给定的字母表 letters,我们可以拼写单词 “dad” (5+1+5)和 “good” (3+2+2+5),得分为 23 。
而单词 “dad” 和 “dog” 只能得到 21 分。
示例 2:

输入:words = [“xxxz”,“ax”,“bx”,“cx”], letters = [“z”,“a”,“b”,“c”,“x”,“x”,“x”], score = [4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,10]
输出:27
解释:
字母得分为 a=4, b=4, c=4, x=5, z=10
使用给定的字母表 letters,我们可以组成单词 “ax” (4+5), “bx” (4+5) 和 “cx” (4+5) ,总得分为 27 。
单词 “xxxz” 的得分仅为 25 。
示例 3:

输入:words = [“leetcode”], letters = [“l”,“e”,“t”,“c”,“o”,“d”], score = [0,0,1,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0]
输出:0
解释:
字母 “e” 在字母表 letters 中只出现了一次,所以无法组成单词表 words 中的单词。

提示:
1 <= words.length <= 14
1 <= words[i].length <= 15
1 <= letters.length <= 100
letters[i].length == 1
score.length == 26
0 <= score[i] <= 10
words[i] 和 letters[i] 只包含小写的英文字母。

回溯

本题可以状态压缩动态规划解决。本题解用回溯。
n = words.length
回溯的层次leve:n。
同层次的回溯:两次回溯,word[leve]选择,不选择。
回溯的状态: cnt[26]记录剩余字符的数量,hasScore记录已经获取的分数。
回溯的调用:BackTrack(leve,0)
CanSub(cnt1[26],cnt2[26]) 需要的字符是否够减。
Sub 减少。
Add 加。

回溯代码

核心代码

class Solution {
public:int maxScoreWords(vector<string>& words, vector<char>& letters, vector<int>& score) {int has[26] = { 0 };for (const auto& ch : letters) {has[ch - 'a']++;}int iRet = 0;std::function<void(int, int)> BackTrack = [&](int leve, int hasScore) {if (words.size() == leve) {iRet = max(iRet, hasScore);return;}			int cur[26] = { 0 };Init(cur, words[leve]);if (CanSub(has, cur)) {Sub(has, cur);int curScore = 0;for (int i = 0; i < 26; i++) {curScore += cur[i] * score[i];}BackTrack(leve + 1, hasScore+ curScore);Add(has, cur);}BackTrack(leve + 1, hasScore);};BackTrack(0, 0);return iRet;}void Init(int* s, const string& str) {for (const auto& ch : str) {s[ch - 'a']++;}}bool CanSub(int* s1, int* s2) {for (int i = 0; i < 26; i++) {if (s1[i] < s2[i]) { return false; }}return true;}void Sub(int* s1, int* s2) {for (int i = 0; i < 26; i++) {s1[i] -= s2[i];}	}void Add(int* s1, int* s2) {for (int i = 0; i < 26; i++) {s1[i] += s2[i];}}
};

测试用例

class Solution {
public:int maxScoreWords(vector<string>& words, vector<char>& letters, vector<int>& score) {int has[26] = { 0 };for (const auto& ch : letters) {has[ch - 'a']++;}int iRet = 0;std::function<void(int, int)> BackTrack = [&](int leve, int hasScore) {if (words.size() == leve) {iRet = max(iRet, hasScore);return;}			int cur[26] = { 0 };Init(cur, words[leve]);if (CanSub(has, cur)) {Sub(has, cur);int curScore = 0;for (int i = 0; i < 26; i++) {curScore += cur[i] * score[i];}BackTrack(leve + 1, hasScore+ curScore);Add(has, cur);}BackTrack(leve + 1, hasScore);};BackTrack(0, 0);return iRet;}void Init(int* s, const string& str) {for (const auto& ch : str) {s[ch - 'a']++;}}bool CanSub(int* s1, int* s2) {for (int i = 0; i < 26; i++) {if (s1[i] < s2[i]) { return false; }}return true;}void Sub(int* s1, int* s2) {for (int i = 0; i < 26; i++) {s1[i] -= s2[i];}	}void Add(int* s1, int* s2) {for (int i = 0; i < 26; i++) {s1[i] += s2[i];}}
};

2023年1月

//通过 x &= (x-1)实现
int bitcount(unsigned x) {
int countx = 0;
while (x) {
countx++;
x &= (x - 1);
}
return countx;
}

class Solution {
public:
int maxScoreWords(vector& words, vector& letters, vector& score) {
vector vCharNums(26);
for (const auto& ch : letters)
{
vCharNums[ch - ‘a’]++;
}
vector vScore(words.size());
for (int i = 0; i < words.size(); i++)
{
for (const auto& ch : words[i])
{
vScore[i] += score[ch - ‘a’];
}
}
m_iUseWordMaskNum = 1 << words.size();
m_vMaskCharNums.assign(m_iUseWordMaskNum, vector(26));
//只选择一个words
for (int i = 0; i < words.size(); i++)
{
auto& v = m_vMaskCharNums[1<<i];
for (const auto& ch : words[i])
{
v[ch - ‘a’]++;
}
}
//多个字符 words
for (int iMask = 1; iMask < m_iUseWordMaskNum; iMask++)
{
if (1 == bitcount(iMask))
{
continue;
}
int iSumMask = (iMask - 1)&iMask;
int iSumMask2 = iMask - iSumMask;
for (int j = 0; j < 26; j++)
{
m_vMaskCharNums[iMask][j] = m_vMaskCharNums[iSumMask][j] + m_vMaskCharNums[iSumMask2][j];
}
}
int iMaxScore = 0;
for (int iMask = 1; iMask < m_iUseWordMaskNum; iMask++)
{
bool bVilid = true;
for (int j = 0; j < 26; j++)
{
if (m_vMaskCharNums[iMask][j] > vCharNums[j])
{
bVilid = false;
break;
}
}
if (bVilid)
{
int iSorce = 0;
for (int i = 0; i < words.size(); i++)
{
if (iMask & (1 << i))
{
iSorce += vScore[i];
}
}
iMaxScore = max(iMaxScore, iSorce);
}
}
return iMaxScore;
}
int m_iUseWordMaskNum;
vector<vector> m_vMaskCharNums;

};

2023年7月

class Solution {
public:
int maxScoreWords(vector& words, vector& letters, vector& score) {
m_c = words.size();
vector vHasChar(26);
for (const auto& ch : letters)
{
vHasChar[ch - ‘a’]++;
}
int iRet = 0;
const int iMaskNum = 1 << m_c;
for (int mask = 0; mask < iMaskNum; mask++)
{
int needChar[26] = { 0 };
for (int j = 0; j < m_c; j++)
{
if (mask & (1 << j))
{
for (const char& ch : words[j])
{
needChar[ch - ‘a’]++;
}
}
}
//字符不足
bool bEnough = true;
int iScource = 0;
for (int j = 0; j < 26; j++)
{
bEnough &= (needChar[j] <= vHasChar[j]);
iScource += score[j] * needChar[j];
}
if (bEnough)
{
iRet = max(iRet, iScource);
}
}
return iRet;
}
int m_c;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
《喜缺全书算法册》以原理、正确性证明、总结为主。
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/12707.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

K8s 二进制部署 上篇

一 K8S按装部署方式&#xff1a; ① Minikube Minikube是一个工具&#xff0c;可以在本地快速运行一个单节点微型K8S&#xff0c;仅用于学习、预览K8S的一些特 性使用。 部署地址&#xff1a;https://kubernetes.io/docs/setup/minikube ② Kubeadmin Kubeadmin也是一个工…

vue网页端控制台展示独有标记

效果展示 实现步骤 1. 新建js文件 定义一个类 用于提供控制台打印日志显示样式的方法 src\libs\util.log.js class Logger {// 定义静态方法static typeColor(type "default") {let color "";switch (type) {case "default":color "#3…

后台菜单数据递归展示

后台菜单数据递归展示 效果示例图aslide.vueaslideItem.vuemenu 效果示例图 aslide.vue <script setup>import {ref} from vue;const props defineProps({isCollapse: {type: Boolean,default: false}});import AslideItem from "./aslideItem.vue"const def…

MIRO时,修改页签“采购订单参考”的数量时,金额不自动计算

MIRO 发票校验时&#xff0c;进入到如下界面&#xff0c;系统参考采购订单自动带出已经收货的金额和数量。 此时如果想要修改数量时&#xff0c;有些用户账号下&#xff0c;金额不自动计算&#xff0c;但是有些用户账号下&#xff0c;数量更改时&#xff0c;系统自动计算和建议…

穷人翻身的秘诀!2024年普通人如何创业赚钱?穷人如何逆袭翻身?普通人创业新风口?

穷人的思维有一个致命的缺陷&#xff0c;就是追求确定性&#xff0c;进而失去了可能性。而赚钱的真相实际上非常残酷。世界上能够赚钱的事情必定是不确定的&#xff0c;能够赚取巨额财富的事情更是极度不确定的。只有面对不确定性&#xff0c;才能让你把竞争对手拦在门外&#…

如何在 Linux 上检查 CPU 和硬盘温度

为了更好地监测您的Linux系统的硬件健康状况&#xff0c;如CPU与硬盘温度、风扇转速等关键指标&#xff0c;采用lm_sensors与hddtemp这两款强大工具是明智之选。以下是关于这些工具的详尽指南&#xff0c;包括它们的功能介绍、安装步骤以及如何配置lm_sensors&#xff0c;旨在为…

ASCLL码表以及字符的相加减

ASCLL码表完整版及解释_acssll码-CSDN博客 #include <getopt.h> #include <stdio.h> #include <stdlib.h>#define MAX_PATH 256 char filename[MAX_PATH 5];int isdigit(int c) {if (c > 0 && c < 9)return 1;return 0; }int main(int argc…

【TypeScript】对象类型的定义

简言 在 JavaScript 中&#xff0c;我们分组和传递数据的基本方式是通过对象。在 TypeScript 中&#xff0c;我们通过对象类型来表示这些对象。 对象类型 在 JavaScript 中&#xff0c;我们分组和传递数据的基本方式是通过对象。在 TypeScript 中&#xff0c;我们通过对象类…

Blender雕刻建模_笔刷纹理和顶点绘制

笔刷纹理 主要用于皮肤&#xff0c;纹理的雕刻。 可以修改映射方式来实现不同绘制效果。 用一张纹理来定义笔刷各个点的强度。其中白色为1&#xff0c;黑色为0。 设置笔刷纹理步骤&#xff1a; -新建一套笔刷 -强度&#xff0c;设为0.15&#xff08;可以根据需求修改&#x…

ACWing471. 棋盘-DFS剪枝

题目 思路 本思路参考博客AcWing 471. 棋盘 - AcWing 约束方程&#xff1a; 代码 #include <iostream> #include <cstring> #include <algorithm>using namespace std;const int N 110, INF 0x3f3f3f3f; int g[N][N], n, m, dist[N][N]; int dx[4] {-1…

接口自动化-requests库

requests库是用来发送请求的库&#xff0c;本篇用来讲解requests库的基本使用。 1.安装requests库 pip install requests 2.requests库底层方法的调用逻辑 &#xff08;1&#xff09;get / post / put / delete 四种方法底层调用 request方法 注意&#xff1a;data和json都…

基于Java+SpringBoot+Mybaties-plus+Vue+elememt 驾校管理系统 设计与实现

一.项目介绍 系统角色&#xff1a;管理员、驾校教练、学员 管理员&#xff1a; 个人中心&#xff1a;修改密码以及个人信息修改 学员管理&#xff1a;维护学员信息&#xff0c;维护学员成绩信息 驾校教练管理&#xff1a;驾校教练信息的维护 驾校车辆管理&…

【R语言】ggplot中点的样式shape参数汇总

ggplot中点的样式展示&#xff1a; library(ggplot2)# 创建数据框 a<- data.frame(x 0:25, y 0:25) # 创建散点图 ggplot(a, aes(x x, y y, shape as.factor(y))) geom_point(size 4) scale_shape_manual(values 0:25) labs(shape "形状") theme(legend.…

产品经理如何进行项目管理?

产品经理如何进行项目管理&#xff1f; 项目管理和产品管理在本质上还是有一定差别的。产品更关注的是产品、功能、方向和反馈&#xff0c;而项目则更关注进度、质量和测试等。如果团队没有项目经理&#xff0c;那么产品经理就需要兼顾对开发人员、项目进度等进行管理。 此时…

K8S搭建

文章目录 K8S搭建配置要求 安装 Kuboard-Spray加载离线资源包规划并安装集群访问集群重启Kubernetes集群Worker节点不能启动许多Pod一直Crash或不能正常访问 containerd配置网络代理 常用的 kubectl 命令&#xff1a; K8S搭建 安装高可用的Kubernetes集群 配置要求 对于 Kub…

【Linux】高效文本处理命令

目录 一.sort命令&#xff08;排序&#xff09; 1.语法格式 2.常用选项 3.相关示例 3.1. 3.2. 二.unip命令&#xff08;去重&#xff09; 1.语法格式 2.常用选项 3.相关示例 3.1. 3.2. 三.tr命令&#xff08;替换&#xff09; 1.语法格式 2.常用选项 3.相关示例…

TiDB学习2:TiDB Sever

目录 1. TiDB Server架构 2. sql语句的解析和编译 2.1 Parse ​编辑 2.2 compile 3. 行转化为KV对(聚簇表) ​编辑4. SQL 读写相关模块 4.1 DistSQL(复杂查询) 4.2 KV(简单查询) 5. 在线DDL相关模块 6. GC机制与相关模块 7. TiDB Server的缓存 8. 热点小表缓存 9. …

做好串口控制是源代码防泄密的基础

在信息化时代&#xff0c;数据安全与保密工作的重要性日益凸显。尤其是在涉密单位&#xff0c;如军工、政府、金融等行业&#xff0c;防泄密工作直接关系到国家安全、社会稳定和企业利益。串口作为计算机与外部设备通信的重要接口&#xff0c;其安全性同样不容忽视。本文将探讨…

react18【系列实用教程】useMemo —— 缓存数据 (2024最新版)

为什么添加了 memo &#xff0c;子组件2依然重新渲染了呢&#xff1f; 因为父组件向子组件2传递了引用类型的数据 const userInfo {name: "朝阳",};<Child2 userInfo{userInfo} />memo() 函数的本质是通过校验Props中数据的内存地址是否改变来决定组件是否重新…

TEMU电商行情分析:未来趋势与盈利机遇探讨

近年来&#xff0c;跨境电商行业风起云涌&#xff0c;其中TEMU作为新兴力量&#xff0c;其市场表现备受关注。那么&#xff0c;TEMU电商现在的行情究竟如何?对于卖家而言&#xff0c;是否仍然是一个能够赚钱的平台呢? 首先&#xff0c;从市场趋势来看 TEMU电商正处于一个快速…