【洛谷P1018】乘积最大 dp+高精度

题目大意:给定一个 N 个数组成的串,可以在串中插入 M 个乘号,求乘积最大是多少。N <= 40

阶段:前 i 个数用了 j 个乘号。
仅用阶段可以表示出一个状态,因此状态转移方程为 \(dp[i][j]=max\{dp[k][j-1]*val(k+1,i),k\in[j,i] \}\)

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=50;

struct node{
    int t[110],len;
    node(){this->clear();}//构造函数需要初始化
    void get_num(int a[maxn],int l,int r){
        this->clear();
        for(int i=r;i>=l;i--)this->t[++this->len]=a[i];
    }
    void operator=(const node& y){
        this->clear();
        for(int i=1;i<=y.len;i++)this->t[i]=y.t[i];
        this->len=y.len;
    }
    bool operator<(const node& y){
        if(this->len^y.len)return this->len<y.len;
        for(int i=this->len;i>=1;i--)if(this->t[i]^y.t[i])return this->t[i]<y.t[i];
        return 0;
    }
    node operator*(const node& y){
        node x;
        for(int i=1;i<=this->len;i++)
            for(int j=1;j<=y.len;j++)
                x.t[i+j-1]+=this->t[i]*y.t[j];//注意 i+j-1
        for(int i=1;i<=105;i++)x.t[i+1]+=x.t[i]/10,x.t[i]%=10;
        for(int i=105;i>=1;i--)if(x.t[i]!=0){x.len=i;break;}
        return x;
    }
    void print(){
        for(int i=this->len;i>=1;i--)printf("%d",this->t[i]);
        puts("");
    }
    void clear(){
        this->len=0;
        memset(this->t,0,sizeof(this->t));
    }
}dp[maxn][maxn];

int n,m,a[maxn];
char s[maxn];

void read_and_parse(){
    scanf("%d%d%s",&n,&m,s+1);
    for(int i=1;i<=n;i++)a[i]=s[i]-'0';
}

void solve(){
    for(int i=1;i<=n;i++)dp[i][0].get_num(a,1,i);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=min(m,i-1);j++)
            for(int k=j;k<i;k++){
                node t;t.get_num(a,k+1,i);
                node x=t*dp[k][j-1];
                if(dp[i][j]<x)dp[i][j]=x;
            }
    dp[n][m].print();
}

int main(){
    read_and_parse();
    solve();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wzj-xhjbk/p/9970514.html
今日推荐