【回溯】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++**实现。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

系统管理(System Keeping):Codigger资源与配置管理(上)

系统管理&#xff08;System Keeping&#xff09;&#xff0c;作为Codigger不可或缺的一部分&#xff0c;为开发者提供全面而高效的资源与配置管理体验。下面&#xff0c;让我们从它的其中三方面来一探究竟其强大的功能如何助力开发者提升工作效率。 一、环境配置&#xff1a;全…

Linux交叉编译

一. 交叉编译 1.使用环境要求 新版本的orangepi-build是在Ubuntu22.04的x64电脑或虚拟机上运行的 lsb_release -a //查看自己的虚拟机版本 因为编译出的SDK大概有16G大小&#xff0c;因此&#xff0c;至少给虚拟机分配50G的大小。 2.获取Linux SDK 方法一&#xff1a;从…

React框架-Next 学习-1

创建一个 Next.js 应用,node版本要高&#xff0c;16.5以上 npm淘宝镜像切为https://registry.npmmirror.com npm config set registry https://registry.npmmirror.com npx create-next-applatest//安装后 使用npm run dev 启动 Next.js 是围绕着 页面&#xff08;pages&am…

智慧园区EasyCVR视频智能管理方案:构建高效安全园区新视界

一、背景分析 园区作为城市的基本单元&#xff0c;是最重要的人口和产业聚集区。根据行业市场调研&#xff0c;90%以上城市居民工作与生活在园区进行&#xff0c;80%以上的GDP和90%以上的创新在园区内产生&#xff0c;可以说“城市&#xff0c;除了马路都是园区”。 园区形态…

高通QCS6490开发(二)AI板卡接口

QCS6490是高通公司针对高端物联网终端而优化的SoC&#xff0c;在性能和功耗上有最优的平衡。《高通QCS6490 AIoT应用开发》是一系列AIoT应用开发文章&#xff0c;介绍如何基于QCS6490平台做AIIoT的应用开发。 本文主要介绍FV01开发板的内部和外部接口。 内部的板载接口如下 接口…

怎么做私域?先来了解私域运营模式!

现在&#xff0c;很多企业都在做私域&#xff0c;但仍旧有很多人会问&#xff1a;我的私域到底要怎么做&#xff1f; 关于这个问题&#xff0c;不同产品无论在消费频次与客单价上&#xff0c;还是在决策链路的长度和复杂度上&#xff0c;都有巨大的差异&#xff0c;消费者需要…

GPT-4o模型介绍和使用方法

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

java项目之企业资产管理系统(springboot+vue+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的企业资产管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 管理员功能有个人中心&…

程序员兼职引起的纠纷?

最近跟朋友聊天&#xff0c;说遇到一些因兼职工作而引发的争议&#xff0c;因为我本人也曾涉足过兼职领域&#xff0c;因此对程序员兼职时可能遇到的各种情况和应遵循的“套路”准则还有有一些发言权的&#xff0c;所以想和大家聊聊如何安全“兼职”的1/2事项~ ✅顺便内推个机会…

前端面试题(二十三)(答案版)

面试形式&#xff1a;线上电话面试&#xff1a;一面&#xff1a;时长30分钟 面试评价&#xff1a;精准考察项目所需技术理论工作实践 面试官的提问大纲&#xff1a;本公司项目要求本人简历 工作经验&#xff1a;2-4年 公司名称&#xff1a;深圳XX&#xff08;想知道的就滴喔…

SHELL编程(一)

目录 一、 Linux操作系统&#xff08;一&#xff09;内核与操作系统&#xff08;二&#xff09;操作系统的功能 二、Linux高级命令&#xff08;一&#xff09; 离线安装 dpkg1. 安装2. 使用3. 查看安装详细信息4. 安装路径5. 不完全删除6. 完全删除 &#xff08;二&#xff09;…

(内地家长)为什么不建议做香港优才计划?香港身份的孩子不是全都能低分上名校!

&#xff08;内地家长&#xff09;为什么不建议做香港优才计划&#xff1f;香港身份的孩子不能都低分上名校&#xff01; 大部分申请香港优才的朋友&#xff0c;应该是冲着孩子教育、高考升学来的。 确实&#xff0c;香港优才申请后拿到的香港身份&#xff0c;对于孩子读书教…

HT3S-ECS-MDN网关引领智能称重新篇章欧姆龙EtherCAT PLC的集成应用案例

在现代化工业生产中&#xff0c;精确的数据采集和高效的通信系统是确保生产流程顺利运行的关键。特别是在称重环节&#xff0c;数据的准确性和实时性对于生产质量和成本控制至关重要。今天&#xff0c;我们将为您介绍一个成功的案例&#xff0c;展示HT3S-ECS-MDN网关如何连接称…

git常用命令及其ignore文件

1.git本地操作命令 # 查看git的版本 git --version # 生成空的本地仓库 git init # 将文件添加到暂存区 git add 文件 # 将暂存区里的文件提交到本地仓库 git commit -m "描述"2.git远程仓库命令 # 添加远程仓库 git remote add origin http://192.168.1.130:9000/…

MySQL 8.0 全新特性详解

MySQL 8.0带来了许多令人兴奋的新特性和优化功能&#xff0c;下面我将逐一详细介绍每个特性&#xff1a; 一、原生数据字典 MySQL 8.0 引入了原生数据字典&#xff0c;取代了之前使用的.frm、.par、.opt等文件来存储元数据。这一改进使得元数据的访问和管理更加高效和直接。原…

【Java基础】初识正则表达式

正则表达式只适用于字符串 匹配matches 实际使用的是String类中定义的方法boolean matches(String regex) public static void piPei( ){String regex"[1][356789]\\d{9}";boolean boo"14838384388".matches(regex);System.out.println(boo); }验证qq号…

第四篇 Asciidoc - MindMap 思维导图 不是事

MindMap 是一种对思维的简单抽象,说到底,就是一个树状结构。 以下是一个样例: Figure 1. MindMap示例 我们的目录结构、模块结构、分类结构等等,都是树型结构,它非常普遍,因此 MindMap 是笔记软件中,获得最多支持的一种图。 精确地说,这类图,是对思维结构的一种映射…

泛微OA中设置SAP接口

泛微OA中设置SAP接口 在泛微oa中有些时候我们需要对接其他系统的接口&#xff0c;这个时候就体现出泛微oa的强大兼容性了。只需要将其他系统的接口在集成中心中的SAP集成中配置即可。 在点击服务注册之后&#xff0c;需要输入服务名称&#xff0c;以及接口名称&#xff0c;并…

2024 手把手教你MathType 7.8中文破解版详细安装激活图文教程

MathType 7.8中文破解版是一款全球最受欢迎的专业数学公式编辑器工具软件,MathType可视化公式编辑器轻松创建数学方程式和化学公式.兼容Office Word,PowerPoint,Pages,Keynote,Numbers等700多种办公软件,用于编辑数学试卷,书籍,报刊,论文,幻灯演示等文档轻松编写各种复杂的物理…

Image Sensor固定模式噪声(FPN)的消除方法

本文介绍Image Sensor固定模式噪声&#xff08;FPN&#xff09;的消除方法。 固定模式噪声&#xff08;FPN&#xff09;英文全称&#xff1a;Fixed Pattern Noise&#xff0c;在Image Sensor调试过程中还是比较常见的&#xff0c;它的特点是噪声位置固定不变&#xff0c;不随采…