• 暑假集训day1 水题 乘法最大


    题目大意:有一个长度为N的字符串,要求用K个乘号将其分成K+1个部分,求各个部分相乘的最大值
    输入:第一行输入N和K,第二行输入一个长度为N的字符串

    算法分析

      1.  这个题只是一个简单的dp(甚至连区间dp都不是)
      2.  dp[i][j]表示前i个数字里面用了j个乘号,而枚举的状态k表示前k个数字用了j-1个乘号,然后用dp[k][j-1]去和后面的数字相乘
      3.  由2可知我们需要一个数组sum[i][j]表示从i到j的数字(也就这和平时的题不一样了):
              想一下如果说后面3个数字为123那么要乘的便是123,而我们平时的算法前缀和或者直接读取数据并不能表示出从1这个位置到3这个位置表示的一百二十三
              所以我们用sum数组提前处理好
          
              `for(int i = 1;i <= n;++i)
    		for(int j = i;j <= n;++j)
    			sum[i][j] = sum[i][j-1]*10 + b[j];`
      `
    
       4.sum数组处理好就是一个简单的dp了,下面是代码
    
    
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5+10;
    int n,m,b[maxn],sum[50][50],dp[50][50];
    char a[maxn];
    
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i = 1;i <= n;++i){
    		scanf(" %c",&a[i]);
    		b[i] = a[i]-'0';
    	}
    	for(int i = 1;i <= n;++i)
    		for(int j = i;j <= n;++j)
    			sum[i][j] = sum[i][j-1]*10+b[j];
    	dp[0][0] = 1;
    	for(int i = 1;i <= n;++i)dp[i][0] = sum[1][i];	
    	for(int i = 1;i <= n;++i)
    		for(int j = 1;j <= i;++j){
    			if(dp[i][i-1] == 0)dp[i][i-1] = 1;
    			dp[i][i-1] *= b[j];
    		}
    	dp[1][0] = b[1];
    	for(int i = 2;i <= n;++i)
    		for(int j = 1;j < i && j <= m;++j)
    			for(int k = j;k < i;++k)
    				dp[i][j] = max(dp[i][j],dp[k][j-1]*sum[k+1][i]);
    	printf("
    %d
    ",dp[n][m]);
    	return 0;
    }
    
  • 相关阅读:
    释放下一代网络应用的能量[转载]
    帮助创建未来的 .NET 客户端开发
    ASP.NET Ajax替代品AjaxWidgets
    Microsoft Surface
    有意思的《致招商银行的公开信》行动!
    Applying DomainDriven Design and Patterns(ADDDP) With examples in C# and .NET
    Silverlight ASP.NET control
    StructureMap 轻量IOC框架
    DDay.iCal an iCalendar class library
    Mono ASP.NET 上几个性能调优技巧
  • 原文地址:https://www.cnblogs.com/2004-08-20/p/13184457.html
Copyright © 2020-2023  润新知