leetcode691.贴纸拼词(DP解法)

贴纸拼词(DP解法)

感觉这题题解太少了,DP解法在CSDN也没找到,所以在自己才“一知半解”时,就想写篇DP解法,为大家提供思路的同时,也希望能得到大家的指点。

题目

我们给出了 N 种不同类型的贴纸。每个贴纸上都有一个小写的英文单词。

你希望从自己的贴纸集合中裁剪单个字母并重新排列它们,从而拼写出给定的目标字符串 target。

如果你愿意的话,你可以不止一次地使用每一张贴纸,而且每一张贴纸的数量都是无限的。

拼出目标 target 所需的最小贴纸数量是多少?如果任务不可能,则返回 -1。

示例1:
输入:

["with", "example", "science"], "thehat"

输出:

3

解释:

我们可以使用 2 个 "with" 贴纸,和 1 个 "example" 贴纸。
把贴纸上的字母剪下来并重新排列后,就可以形成目标 “thehat“ 了。
此外,这是形成目标字符串所需的最小贴纸数量。

DP思路:

假设

target="hat"
sticker1="haha"
sticker2="tata"

总共有1<<target.size()种状态,从开始一张没贴的000到最后全部贴好的111,
第一次:

000->我们可以用sticker1截取a,h用来拼,即110
也可以用sticker2截取t,a拼,即011
所以状态110和011所花贴纸均为1:
011->1
110->1
其余地方均为-1.

第二次:

状态向后遍历,遇到-1说明这些地方没有可用的贴纸直接跳过,直到遇到不为-1.
011->此处不为-1,继续截取贴纸拼写,发现可以从haha截取h拼,所以
111->2(tata+haha).

大致过程就是这样,接下来可以享用代码,加深理解:

class Solution {
public:
    int minStickers(vector<string>& stickers, string target) {
        int m=target.size();
        vector<int>dp(1<<m,-1);
        dp[0]=0;//长度为0无需贴纸.
        for(int State=0;State<(1<<m);State++){
            if(dp[State]==-1)//无可用贴纸直接跳过
            continue;
            for(string sticker:stickers){
                int initialState=State;//在当前状态下往最终状态继续拼
                for(char ch:sticker){//将贴纸的字符截取
                    for(int i=0;i<m;i++){
                        if((initialState>>i)&1==1)//之前已经贴好,则跳过
                        continue;
                        if(ch==target[i]){//否则就将当前字符取用,换下一个字符
                            initialState|=(1<<i);
                            break;
                        }
                    }
                }
                if(dp[initialState]==-1||dp[initialState]>dp[State]+1)//自己思考思考
                dp[initialState]=dp[State]+1;
            }
        }
        return dp[(1<<m)-1];
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值