SSL2833 2017年11月3日提高组T1 Alice的疑问(数位dp)

来源:互联网 发布:最新网络语言大全 编辑:程序博客网 时间:2024/05/19 07:25

2017年11月3日提高组T1 Alice的疑问

Description

  当Alice在浏览数学书时,看到一个等式A=S,奇怪的是A和S并不相等。Alice发现可以通过在A中添加加号“+”从而使得等式成立。
  编程计算最少需要插入多少加号使得等式成立。允许每个数有多个前导0

Input

 输入第一行包含一个等式形式为A=S。
  A和S都是没有前导0的正整数,并保证不相同。
  A最多有1000位。
  S<=5000。
  输入保证有解。

Output

 输出最少需要插入的加号数量。

Sample Input

143175=120
Sample Output

2

分析:设f[i][j]表示到第i位,和为j,最少加了多少个加号
f[k][j+z]=min{f[i][j]+1},k为i+1~n,z为i+1~k位组成的数z>s1break
然后转移O(n^2m),其实有很多前导0,这个很容易被卡
设fl[i]表示第i后面非0的第1位,n^2暴力求
然后k只用枚举fl[i]~fl[i+3],然后就可以O(nm)啦
当然也可以如果很多个0在一起,变成3个就好

代码

#include <cstdio>#include <string>#include <cstring>#define N 6000using namespace std;int min(int x,int y){    return x<y?x:y;}int a[1005],num[1005],f[1005][5005],s;int main(){    char st[N];    scanf("%s",&st);    int x=0;    while (st[x]!='=') x++;    for (int i=0;i<x;i++)        a[i]=st[i]-'0';    for (int i=x+1;i<strlen(st);i++)        s=s*10+(st[i]-'0');    int l=0,i=0;    while (i<x)    {        int o=i;        while (a[o]==0&&o<x-1) o++;        if (o-i+1>3)         {            num[++l]=0;            num[++l]=0;            num[++l]=0;            i=o;            continue;        }        else num[++l]=a[i++];    }    memset(f,127,sizeof f);    f[0][0]=-1;    for (int i=0;i<=l;i++)        for (int j=0;j<=s;j++)        {            int sum=0;            for (int k=i+1;k<=l;k++)            {                sum=sum*10+num[k];                if (sum>s) break;                f[k][j+sum]=min(f[k][j+sum],f[i][j]+1);            }        }    printf("%d",f[l][s]);}
阅读全文
0 0