当前位置:网站首页>贴纸拼词 —— 记忆化搜索 / 状压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];
}
};
边栏推荐
- 2023年航空航天、机械与机电工程国际会议(CAMME 2023)
- BGP实验(含MPLS)
- 带你造轮子,自定义一个随意拖拽可吸边的悬浮View组件
- 网络带宽监控,带宽监控工具哪个好
- "Miscellaneous" barcode by Excel as a string
- LeetCode third topic (the Longest Substring Without Repeating Characters) trilogy # 3: two optimization
- 第1章:初识数据库与MySQL----MySQL安装
- vxe-table 从页面批量删除数据 (不动数据库里的数据)
- Mvc, Mvp and Mvvm
- C 学生管理系统 显示链表信息、删除链表
猜你喜欢

ENS域名注册量创历史新高 逆市增长之势?光环之下存在炒作风险

ML18-自然语言处理

typescript53-泛型约束

Web3 security risks daunting?How should we respond?

Apple told Qualcomm: I bought a new campus for $445 million and may plan to speed up self-development of baseband chips

Getting started with MATLAB 3D drawing command plot3

全面讲解 Handler机制原理解析 (小白必看)

Modulo operation (MOD)

字符串变形

pcl点云数据 转化为 Eigen::Map
随机推荐
面试必问的HashCode技术内幕
dynamic memory two
一文参透分布式存储系统Ceph的架构设计、集群搭建(手把手)
Analysis of usage scenarios of mutex, read-write lock, spin lock, and atomic operation instructions xaddl and cmpxchg
Vant3 - click on the corresponding name name to jump to the next page corresponding to the location of the name of the TAB bar
求解同余方程 数论 扩展欧几里得
电子组装行业对MES管理系统的需求分析
【日志框架】
Google Earth Engine - Calculates the effective width of rivers using publicly available river data
fsdbDump用法
跨域问题解决方式 代理服务器
研究生新生培训第四周:MobileNetV1, V2, V3
How to find the cause of Fiori Launchpad routing errors by single-step debugging
114. How to find the cause of Fiori Launchpad routing error by single-step debugging
Electronics manufacturing enterprise deployment WMS what are the benefits of warehouse management system
【超详细教程】LVS+KeepAlived高可用部署实战应用
数据库扩容也可以如此丝滑,MySQL千亿级数据生产环境扩容实战
第1章:初识数据库与MySQL----MySQL安装
iframe通信
typescript58-泛型类