有关删除数字的dp问题

题意:给定一个数字(100000位)求删除最少的数字使其%6为0(不能有前导0);
Input 1

0010456

Output 1

4

Input 2

11

Output 2

-1s

#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int dp[100010][10];//dp[i][j]代表前i位余数为j时最少需要删除的数字个数
void solve(string s)
{
    memset(dp,0x3f,sizeof(dp));
    int len=s.size();
    for(int i=0; i<len; i++)
    {
        if(s[i]!='0')//预处理当前数字不为0时
        {
            int tmp=(s[i]-'0')%6;
            dp[i+1][tmp]=i;//删除前面的所有数使得余数为tmp
        }
        for(int j=0; j<6; j++)//枚举余数
        {
            dp[i+1][j]=min(dp[i+1][j],dp[i][j]+1);//当前余j取前一位余j的长度,删掉当前位(前一位余j的长度加一);
            int tmp=(j*10+s[i]-'0')%6;//前一位余j到当前位就会余tmp
            dp[i+1][tmp]=min(dp[i+1][tmp],dp[i][j]);//取前一位余j余当前位余tmp的最小值
        }
    }
}
int main()
{
    string s;
    while(cin>>s)
    {
        solve(s);
        int len=s.size();
        int ans=inf;
        for(int i=0; i<len; i++)//如果有0课删除len-1位
            if(s[i]=='0')
            {
                ans=len-1;
                break;
            }
            ans=min(ans,dp[len][0]);
            if(ans==inf)
                printf("-1s\n");
            else
            printf("%d\n",len-ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值