NYOJ746 整数划分

该题是一道区间DP的题目,做了几道区间DP,说起来高大上,也就是DP在区间内的形式而已,核心思想还是要想到转移->规划。

题意是在n位数中间加m个称号,使得最终乘积最大。

状态转移方程如下:

dp[ i ][ j ]=max( dp[ i ][ j ],dp[ k ][ j - 1]*a[ k + 1][ i ])

a[ i ][ j ]表示第 i 位到第 j 位组成的数,要预处理一下。

再来说转移方程,无非两种情况,加或不加。

在k位不加称号,便是dp[ i ] [ j ],

如果加了称号,便是第k+1位到 i 位组成的数与dp [ k ][ j - 1](k位加了j-1个乘号的最大值)相乘的结果。

在以上两者中取个最大值,便形成了转移方程。

代码如下:

#include<iostream>  
#include<string.h>  
#include<algorithm>  
using namespace std;  
#define ll long long 
ll dp[20][20],f,a[25][25];  
int main()  
{  
    int t,n,m,i,j,b[25];  
    char s[25],k;  
    cin>>t;  
    while(t--)  
    {  
        cin>>s>>m;  
        n=strlen(s);  
        memset(dp,0,sizeof(dp));  
        for(i=0;i<n;i++)  
            b[i]=s[i]-'0';  
        for(i=0;i<n;i++)  
        {  
            f=0;  
            for(j=i;j<n;j++)  
            {  
                f=f*10+b[j];  
                a[i][j]=f;  
            }  
        }  
        for(i=0;i<n;i++)  
            dp[i][0]=a[0][i];//没有乘号时的dp值。  
        for(i=0;i<n;i++)  
            for(k=0;k<i;k++)  
                for(j=1;j<m;j++)  
                    dp[i][j]=max(dp[i][j],dp[k][j-1]*a[k+1][i]);  
        cout<<dp[n-1][m-1]<<endl;  
     }  
     return 0;  
} 

猜你喜欢

转载自www.cnblogs.com/fantastic123/p/8988730.html