当前位置:网站首页>贴纸拼词 —— 记忆化搜索 / 状压DP
贴纸拼词 —— 记忆化搜索 / 状压DP
2022-08-04 00:56:00 【小酒窝.】
https://leetcode.cn/problems/stickers-to-spell-word/
题意
给定一个长度为 n 的字符串 S,给定 m 种字符串 a[],每种字符串无限个。
现在要选出一些字符串,将其每个字符剪切后可以拼接成字符串 S。
问,最少要选多少个字符串?
1 ≤ n ≤ 15 , 1 ≤ m ≤ 50 , 1 ≤ ∣ a i ∣ ≤ 10 1 \le n \le 15,\ 1 \le m \le 50,\ 1 \le |a_i| \le 10 1≤n≤15, 1≤m≤50, 1≤∣ai∣≤10
思路
目标字符串长度很小,考虑记忆化搜索:
对于当前的字符串 s 来说,选择一个字符串 t,将 s 中能由字符串 t 剪切得到的位置删掉后得到新串,然后递归到这个新串。
如果当前串为空,说明到了终点,返回 0。
否则,返回 m 个新串到达终点的答案的最小值 + 1。
为了方便转移,可以将长度最大为 15 的串进行状态压缩,对于某一位来说如果是 1 说明没删,如果是 0 说明删掉了,状压成一个整数。
class Solution {
public:
string aim;
int x, ans = 1e9;
vector<string> st;
int f[1<<15];
int cnt[60][30];
int tcnt[30];
void pre()
{
for(int i=0;i<st.size();i++)
{
string s = st[i];
for(char c : s) cnt[i][c-'a']++;
}
}
int dfs(int x)
{
int sum = 1e9;
if(x == 0) return 0;
for(int i=0;i<st.size();i++)
{
for(int j=0;j<26;j++) tcnt[j] = cnt[i][j];
int tx = x;
for(int j=0;j<15;j++) //遍历所有位置,将能用串 i 删掉的位置都删掉
{
if(!(x >> j & 1)) continue;
char c = aim[j];
if(tcnt[c - 'a']) tcnt[c - 'a']--, tx -= 1<<j;
}
if(tx == x) continue; //如果串无变化不再递归当前值,否则会陷入循环
if(!f[tx]) dfs(tx); //剪枝
sum = min(sum, f[tx] + 1); //递归到新串
}
f[x] = sum; //记忆化
return sum;
}
int minStickers(vector<string>& stickers, string target) {
aim = target;
st = stickers;
pre();
for(int i=0;i<target.size();i++) x += 1<<i;
int ans = dfs(x);
if(ans == 1e9) return -1;
return ans;
}
};
按照这种思路同样可以用 bfs 来做,对于当前串能够通过选择一个操作串得到一个新串,操作次数为1,最终首次得到目标串的操作次数便是最小操作次数。
同样,可以转化为状压DP的做法。
遍历所有集合,对于当前集合来说,选择一种字符串删除若干元素来得到一个新的集合,用新集合状态 + 1 得到当前集合状态。
class Solution {
public:
int cnt[60][30];
int tcnt[30];
int f[1<<15];
int minStickers(vector<string>& stickers, string target) {
for(int i=0;i<stickers.size();i++)
{
string s = stickers[i];
for(char c : s)
cnt[i][c - 'a'] ++;
}
int n = target.size();
for(int i=0;i<1<<n;i++) f[i] = 1e9;
f[0] = 0;
for(int i=0;i<1<<n;i++)
{
int x = i;
for(int j=0;j<stickers.size();j++)
{
int tx = x;
for(int k=0;k<26;k++) tcnt[k] = cnt[j][k];
for(int k=0;k<n;k++)
{
if(!(x >> k & 1)) continue;
if(tcnt[target[k] - 'a']) tcnt[target[k] - 'a']--, tx -= 1<<k;
}
f[x] = min(f[x], f[tx] + 1);
}
}
if(f[(1<<n) - 1] == 1e9) return -1;
return f[(1<<n) - 1];
}
};
边栏推荐
- c语言分层理解(c语言指针(上))
- The 600MHz band is here, will it be the new golden band?
- Spinnaker调用Jenkins API 返回403错误
- Salesforce's China business may see new changes, rumors may be closing
- Shell编程之循环语句(for、while)
- typescript52-简化泛型函数调用
- 求解同余方程 数论 扩展欧几里得
- 虚拟机CentOS7中无图形界面安装Oracle
- LeetCode third topic (the Longest Substring Without Repeating Characters) trilogy # 3: two optimization
- 字符串的排列
猜你喜欢

typescript50 - type specification between cross types and interfaces

Electronics manufacturing enterprise deployment WMS what are the benefits of warehouse management system

OpenCV如何实现Sobel边缘检测

《Greenplum构建实时数据仓库实践》简介

600MHz频段来了,它会是新的黄金频段吗?

After building the pytorch environment, the pip and conda commands cannot be used

LYVE1抗体丨Relia Tech LYVE1抗体解决方案

手撕Gateway源码,今日撕工作流程、负载均衡源码

typescript55 - generic constraints

【虚拟户生态平台】虚拟化平台安装时遇到的坑
随机推荐
LYVE1抗体丨Relia Tech LYVE1抗体解决方案
【超详细】手把手教你搭建MongoDB集群搭建
The 600MHz band is here, will it be the new golden band?
电子组装行业对MES管理系统的需求分析
【日志框架】
typescript51 - basic use of generics
Eight things to pay attention to in spot silver
The problem of disorganized data output by mnn model
typescript56-泛型接口
第1章:初识数据库与MySQL----MySQL安装
如何用C语言代码实现商品管理系统开发
boot issue
【详细教程】一文参透MongoDB聚合查询
【虚拟户生态平台】虚拟化平台安装时遇到的坑
数据库扩容也可以如此丝滑,MySQL千亿级数据生产环境扩容实战
typescript56 - generic interface
vxe-table 从页面批量删除数据 (不动数据库里的数据)
2023年航空航天、机械与机电工程国际会议(CAMME 2023)
View the version number of CUDA, pytorch, etc.
typescript51-泛型的基本使用