洛谷P1018乘积最大——区间DP

题目:https://www.luogu.org/problemnew/show/P1018

区间DP+高精,注意初始化和转移的细节。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#define MAXN 20005
using namespace std;
typedef long long ll;
ll n,k,a[45],f[45][7][MAXN],tmp[MAXN],num[MAXN];
char dc[45];
void nm(ll l,ll r)
{
//    printf("l=%lld r=%lld
",l,r);
    num[0]=r-l+1;
    for(ll i=l;i<=r;i++)//正存即可 
        num[i-l+1]=a[i];
//    for(int i=1;i<=num[0];i++)printf("%lld",num[i]);
//    cout<<endl;
}
void init()
{
    a[0]=strlen(dc);
    for(ll i=1;i<=a[0];i++)
    {
        a[i]=dc[a[0]-i]-'0';
//        memset(num,0,sizeof num);
//        nm(1,i);
        memcpy(f[i][0],f[i-1][0],sizeof f[i-1][0]);//注意初始化! 
        f[i][0][0]++;f[i][0][i]=a[i];
    }
}
void ch(ll a[],ll b[])
{
    tmp[0]=a[0]+b[0]-1;
    for(ll i=1;i<=a[0];i++)
        for(ll j=1;j<=b[0];j++)
        {
            tmp[i+j-1]+=a[i]*b[j];
            tmp[i+j]+=tmp[i+j-1]/10;
            tmp[i+j-1]%=10;
        }
    if(tmp[tmp[0]+1])tmp[0]++;
}
bool com(ll a[],ll b[])
{
    if(a[0]>b[0])return 1;
    if(a[0]<b[0])return 0;
    for(ll i=a[0];i;i--)
    {
        if(a[i]>b[i])return 1;
        if(a[i]<b[i])return 0;
    }
    return 0;
}
void print(ll a[])
{
    for(ll i=a[0];i;i--)
        printf("%lld",a[i]);
}
int main()
{
    scanf("%lld%lld",&n,&k);
    cin>>dc;
    init();
//    f[1][1][0]=1;f[1][1][1]=1;
    for(ll i=2;i<=n;i++)
        for(ll l=1;l<=min(i-1,k);l++)
            for(ll j=l;j<i;j++)//从l开始!!!
            {
//                f[i][l]=max(f[j][l-1]*num(j+1,i),f[i][l]);
                memset(tmp,0,sizeof tmp);
                memset(num,0,sizeof num);
                nm(j+1,i);
                ch(f[j][l-1],num);
                if(com(tmp,f[i][l]))memcpy(f[i][l],tmp,sizeof tmp);
            }
    print(f[n][k]);
    return 0;
}
原文地址:https://www.cnblogs.com/Zinn/p/8533365.html