P1874 快速求和

原题链接

题解

细节很多,看代码

code

#include<bits/stdc++.h>
using namespace std;
string s;
int num;
int vis[55][100005]={0};
int ans[55][100005]={0};
int sou(int pos,int left)//以pos为开头到结尾的数是否能够等于left,如果能需要几个加号
{
    if(vis[pos][left]) return ans[pos][left];//记忆化搜索
    vis[pos][left]=1;


    int now=0;
    for(int i=pos;s[i];i++)
    {
        now=now*10+s[i]-'0';
        if(now>=1e8) break;//防止溢出,只要证明剩下的数字能大于left就好了
    }

    //printf("pos:%d  left:%d  now:%d\n",pos,left,now);
    if(left>now)
    {
        ans[pos][left]=-1;
        return -1;//代表不可能
    }
    if(left==now)
    {
        ans[pos][left]=0;
        return 0;//需要零个加号
    }


    int sum=0;
    int pluses=2e9;
    for(int i=pos;i<s.size()-1;i++)//放+号的位置
    {
        sum=sum*10+s[i]-'0';
        if(sum>left)break;//一是防止溢出,二是防止无效搜索
        int cnt=sou(i+1,left-sum);
        if(cnt>=0) pluses=min(cnt+1,pluses);
    }
    ans[pos][left]=(pluses==2e9?-1:pluses);
    return ans[pos][left];
}
int main()
{
    cin>>s>>num;

    cout<<sou(0,num)<<"\n";
    return 0;
}

posted @ 2024-05-08 13:21  纯粹的  阅读(37)  评论(0)    收藏  举报