nyoj746 整数划分

nyoj746 http://acm.nyist.net/JudgeOnline/problem.php?pid=746

一道区间dp的题目:

设:a[i][j]为那一串数字中从第i位到第j位的数是多少

f[i][j]为从第一位到第i位分成j段的最大乘积,则有:

f[i][j]=max(f[u][j-1]*a[u+1][i])  (u=1toi-1)  u表示分割点

把1~u分成j-1份,其最大乘积就是f[u][j-1],再把剩下的u+1~i的数(a[u+1][i])作为最后一份,两者相乘便可以求出f[i][j].

边界:f[1~n][1]=a[1][1~n]

注意把j放在最外层循环。

代码:

//f[i][j]=max(f[u][j-1]*a[u+1][i])  (u=1toi-1)
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring> 
#include<cmath> 
#include<stack>
#define Size 25
using namespace std;

long long T; 
long long f[Size][Size];
long long a[Size][Size];
char c[Size];
int n,m;

int ctoi(char c){
    return c-'0';
}

int stoi(int i,int j){
    int num=0;
    for(int k=j;k>=i;k--){
        num+=ctoi(c[k])*pow(10,j-k);
    }
    return num; 
}

int main(){
    cin>>T;
    
while(T--){
    //初始化 
    memset(f,0,sizeof(f));
    memset(a,0,sizeof(a));
    
    //输入 
    cin>>c+1>>m;
    n=strlen(c+1);
    
    //初始化a数组 
    for(int i=1;i<=n;i++){
        for(int j=i;j<=n;j++){
            a[i][j]=stoi(i,j);
            //cout<<a[i][j]<<' ';
        }
        //cout<<endl;
    }
    
    //边界条件 
    for(int i=1;i<=n;i++)f[i][1]=a[1][i];
    //DP求解 
    for(int j=2;j<=m;j++){
        for(int i=j;i<=n;i++){
            for(int u=1;u<i;u++){
                if(f[u][j-1]*a[u+1][i] > f[i][j]){
                    f[i][j] = f[u][j-1]*a[u+1][i];
                }
            }
        }
    }
    
    //输出最大乘积 
    cout<<f[n][m]<<endl;
}

    return 0;
} 
原文地址:https://www.cnblogs.com/FuTaimeng/p/5272604.html