• 【wikioi】1017 乘积最大


    题目链接

    算法:划分型DP

    非常典型的一道题目,划分型DP

    题目描述:

    设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子:有一个数字串:312, 当N=3,K=1时会有以下两种分法:

    1)  3*12=36

    2)  31*2=62

    这时,符合题目要求的结果是:31*2=62现在,请你帮助你的好朋友XZ设计一个程序,求得正确的答案。

    设数字串为a1a2a3……an。当k=1时,最大值为

    max{a1*a2a3……an,  a1a2*a3……an,  ……  ,  a1a2a3……an-1*an}

    当k=2时,最大值为

    max{a1*a2*a3……an,  a1*a2a3……*an,  ……  ,  a1a2a3……*an-1*an}

    引入记号f[i,k]表示从a0到ai,插入k个乘号所取得的最大值,用c[i,j]表示从ai到aj的数字列,则:

    K=1时

    f[n,1]=max{c[1,1]*c[2,n],  c[1,2]*c[3,n],  ……  ,  c[1,n-1]*c[n,n]}

    K=2时

    f[n,2]=max{f[n-1,1]*c[n,n],  f[n-2,1]*c[n-1,n],  ……  ,  f[2,1]*c[3,n]}

    所以导出

    f[n,k]=max{f[n-1,k-1]*c[n,n],  f[n-2,k-1]*c[n-1,n],  .......  , f[k,k-1]*c[k+1,n]}

    我们用F[n][k]来表示f[n,k],表示划分k次得到的数最大,用A[i][j]表示c[i,j]

    得到:

    F[i][1] = max(F[i][1], A[1][j]*A[j+1][i])  (1 <= j < i)

    F[i][k] = max(F[i][k], A[j+1][i]*F[j][k-1]) (k <= j < i)

    其实这里可以简化成:

    F[i][0] = A[1][i]  (1 <= i <= n)

    F[i][k] = max(F[i][k], A[j+1][i]*F[j][k-1]) (k <= j < i, 1 <= k <= m) m是要添加的乘号数目

    而且发现,方程是以划分次数k为阶段,且顺序是递增(从k到i枚举j即可),那么我们就自底向上的来递推

    所以顺序就一木了然了

    上代码:

    #include <iostream>
    #include <string>
    #include <algorithm>
    using namespace std;
    
    int n, m, i, j, k;
    const int MAXK = 10;
    const int MAXN = 100;
    int c[MAXN] = {0}, A[MAXN][MAXN] = {{0,0}}, F[MAXN][MAXK] = {{0,0}};
    int makeConut(int x, int y)   //求x到y之间的数字列
    {
    	int ans = 0;
    	while(x <= y) ans = ans * 10 + c[x++];
    	return ans;
    }
    
    int main()
    {
    	string str;
    	cin >> n >> m;
    	cin >> str;
    	for(i = 1; i <= n;i++) c[i] = (str[i-1]-'0');
    	for(i = 1; i <= n; i++)
    		for(j = 1; j <= n; j++)
    			A[i][j] = makeConut(i, j);  //初始化A数组
    	//初始化k=0时的情况
    	//F[i][0] = A[1][i]  (1 <= i <= n)
    	for(i = 1; i <= n; i++)
    		F[i][0] = A[1][i];
    	//DP
    	//F[i][k] = max(F[i][k], A[j+1][i]*F[j][k-1]) (1 <= k <= m)
    	for(k = 1; k <= m; k++)
    		for(i = k+1; i <= n; i++)
    			for(j = i-1; j >= k; j--)
    				F[i][k] = max(F[i][k], A[j+1][i]*F[j][k-1]);
    	cout << F[n][m] << endl;
    	return 0;
    }
  • 相关阅读:
    ★★★5230打字慢的解决方法...绝对有用...只需要在手机上轻微的设置一下(转)
    IT公司中最流行的10种编程语言(转)
    Windows下安装Object C开发环境,及Hello Word(转)
    [图]AMD的CPU在VirtualBox中安装Mac OS X 10.6(转)
    How_to_Handle_Pointer_Events_in_a_Custom_Control(转)
    Cannot obtain license for Compiler (feature compiler) with license version >= 2.2(转)
    GNUstep Gorm第一个视窗程序,第一个图形界面,第一个helloworld gui(转)
    Symbian源码分析(转)
    Symbian计算MD5(转)
    Does not support program for platform "WINSCW"
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/3521798.html
Copyright © 2020-2023  润新知