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

news2024/9/20 0:53:35

本文涉及知识点

回溯
力扣难道: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.coloradmin.cn/o/1680655.html

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

相关文章

Google I/O盛会省流全内容总结:AI模型家族革新与前沿技术应用的广阔前景

昨晚的Google I/O 发布会主要聚焦于AI模型和应用的更新与扩展&#xff0c;特别在生成模型领域取得了显著进步。以下是模型层面内容的简要总结&#xff1a; DeepMind官网链接&#xff1a;https://deepmind.google/ Google Veo官方&#xff1a;https://deepmind.google/technol…

小程序框架是智能融媒体平台构建的最佳线路

过去5年&#xff0c;媒体行业一直都在进行着信息化建设向融媒体平台建设的转变。一些融媒体的建设演变总结如下&#xff1a; 新闻终端的端侧内容矩阵建设&#xff0c;如App新闻端&#xff0c;社交平台上的官方媒体等新闻本地生活双旗舰客户端&#xff0c;兼顾主流媒体核心宣传…

幻兽帕鲁Palworld服务器手动+docker部署方法+备份迁移

目录 帕鲁部署官方文档帕鲁手动安装法手动安装steamcmd通过steamcmd安装帕鲁后端 docker容器一键部署幻兽帕鲁绿联云NAS机器部署幻兽帕鲁客户端连接附录1&#xff1a;PalServer.sh的启动项附录2&#xff1a;配置文件游戏存档保存和迁移 关于阿里云计算巢 帕鲁部署官方文档 htt…

监控 Apache Web 服务器性能指标

Apache Web 服务器以其可靠性、灵活性和强大的功能而闻名&#xff0c;几十年来一直是互联网的支柱&#xff0c;从小型个人博客到大型电子商务平台&#xff0c;Apache 的多功能性使其能够轻松处理各种 Web 应用程序。 Apache 的 Web 服务器是如何工作的 尽管 Web 服务器涉及复…

Audio Hijack for Mac 激活版:音频录制与处理软件

Audio Hijack for Mac&#xff0c;让您的音频创作更加高效、便捷。它支持多种音频格式的录制和导出&#xff0c;包括MP3、AAC、WAV等&#xff0c;让您的音频作品具有更广泛的兼容性。同时&#xff0c;软件界面简洁明了&#xff0c;操作流畅自然&#xff0c;即使您是初学者也能快…

5.2 操作系统安装必备知识

目前操作系统安装方式接近于全自动化&#xff0c;用户无需做过多操作就能完成操作系统安装。但是操作系统安装也有其复杂的一面&#xff0c;例如固件及分区表的不同就会导致操作系统安装失败。本节主要介绍系统安装的一些必备知识。 5.2.1 BIOS 概述 BIOS(Basic Input/Output …

【运维自动化-配置平台】如何自动应用主机属性

主要用于配置主机属性的自动应用。当主机发生模块转移或模块新加入主机时&#xff0c;会根据目标模块配置的策略自动触发修改主机属性&#xff0c;比如主机负责人、主机状态。主机属性自动应用顾名思义是应用到主机上&#xff0c;而主机是必须在模块下的&#xff0c;所以有两种…

武汉星起航:中国卖家借力亚马逊跨境电商平台,拓展全球销售市场

随着互联网技术的飞速发展&#xff0c;跨境电商已成为连接全球消费者与卖家的重要桥梁。作为全球领先的跨境电商平台&#xff0c;亚马逊凭借其强大的品牌影响力、丰富的商品资源和高效的物流体系&#xff0c;为全球消费者提供了一个便捷、安全的购物环境。在这个平台上&#xf…

Google Chrome 设备工具栏原理

1.不同预览模式 2.计算出缩放比 3.固定滚动偏移 关键代码&#xff1a; overview&#xff1a; ratioW getChildRect().width / getParentRect().width ratioH getChildRect().height / getParentRect().height maxRatio max(ratioW, ratioH) if(maxRatio < 1) return 1 …

【UE5.1 角色练习】02-添加慢走、快速跑、蹲伏功能

目录 前言 步骤 一、慢走 二、快速跑 三、蹲伏 前言 在上一篇文章基础上&#xff08;【UE5.1 角色练习】01-使用小白人蓝图控制商城角色移动&#xff09;继续实现角色的慢走、快速跑以及蹲伏功能 步骤 一、慢走 1. 打开项目设置&#xff0c;添加一个操作映射&#x…

六西格玛管理培训对企业有哪些实际帮助?

当下&#xff0c;企业要想脱颖而出&#xff0c;不仅要有创新思维和敏锐的市场洞察力&#xff0c;更要有高效的管理体系和严谨的质量控制手段。而六西格玛管理培训正是这样一项能够帮助企业实现提质增效、提升竞争力的关键举措。那么&#xff0c;六西格玛管理培训对企业究竟有哪…

邦注科技 工业冷水机的风冷和水冷的区别介绍

工业冷水机在工业生产中扮演着重要角色&#xff0c;特别是在需要精确控制温度的应用中。风冷式冷水机和水冷式冷水机是两种常见的类型&#xff0c;它们之间存在一些显著的区别。 热交换的来源不同&#xff1a; 风冷式冷水机&#xff1a;热交换的来源是气体。它采用空气冷却方…

计算机网络 -- 序列化与反序列化

一 协议的重要性 我们都知道&#xff0c;在进行网络通信的过程中&#xff0c;通信的双方可以是不同的设备&#xff0c;不同的平台&#xff0c;不同的平台&#xff0c;比如说&#xff0c;手机用户和电脑用户进行通信&#xff0c;ios系统和安卓系统进行通信。 自己的数据&#xf…

从RTTR谈Reflection机制

虽然C11引入了RTTI、Metaprogramming 等技术&#xff0c;但C在Reflection编程方面依旧功能有限。在社区上&#xff0c;RTTR则提供了一套C编写的反射库&#xff0c;补充了C在Reflection方面的缺陷。 零、环境 操作系统Windows 11Visual StudioVisual Studio Community 2022 CMa…

Broad Learning System (BLS) 宽度学习系统

宽度学习&#xff08;Broad Learning System, BLS&#xff09;是一种有效的神经网络学习框架&#xff0c;旨在通过扩展网络的宽度而不是深度来提高学习能力和效率。与传统的深度学习相比&#xff0c;宽度学习通过堆叠多层特征节点和增强节点来构建网络&#xff0c;从而避免了深…

Spring Boot 中的秘密武器:ApplicationContextInitializer 接口揭秘

Spring Boot 中的秘密武器&#xff1a;ApplicationContextInitializer 接口揭秘 在 Spring Boot 应用开发中&#xff0c;ApplicationContextInitializer接口是一个强大的扩展点&#xff0c;它允许开发者在 Spring 上下文刷新之前执行自定义逻辑。本文将详细讲解ApplicationCont…

练习题(2024/5/15)

1有多少小于当前数字的数字 给你一个数组 nums&#xff0c;对于其中每个元素 nums[i]&#xff0c;请你统计数组中比它小的所有数字的数目。 换而言之&#xff0c;对于每个 nums[i] 你必须计算出有效的 j 的数量&#xff0c;其中 j 满足 j ! i 且 nums[j] < nums[i] 。 以…

STM32 HAL TM1638读取24个按键

本文分享一下天微电子的另一款数码管按键驱动芯片TM1638的单片机C语言驱动程序。 笔者采用的MCU是STM32单片机&#xff0c;STM32CubeMX Keil5开发&#xff0c;使用了HAL库。 一、TM1638介绍 1、基础信息 TM1638属于一款LED驱动控制专用电路&#xff0c;其特性如下&#xf…

基于模糊神经网络的嘉陵江水质预测

部分实验代码 %输入层xinputn(:,k);%输入层结算for i1:Ifor j1:Mu(i,j)exp(-(x(i)-c(j,i))^2/b(j,i));endend%模糊规则计算for i1:Mw(i)u(1,i)*u(2,i)*u(3,i)*u(4,i)*u(5,i)*u(6,i);end addwsum(w);for i1:Myi(i)p0_1(i)p1_1(i)*x(1)p2_1(i)*x(2)p3_1(i)*x(3)p4_1(i)*x(4)p5…

[NOIP2011 普及组] 瑞士轮

[NOIP2011 普及组] 瑞士轮 题目背景 在双人对决的竞技性比赛&#xff0c;如乒乓球、羽毛球、国际象棋中&#xff0c;最常见的赛制是淘汰赛和循环赛。前者的特点是比赛场数少&#xff0c;每场都紧张刺激&#xff0c;但偶然性较高。后者的特点是较为公平&#xff0c;偶然性较低…