整数划分+乘积最大

记得开long long啊

题目描述
如何把一个正整数N(N长度<20)划分为M(M>1)个部分,使这M个部分的乘积最大。N、M从键盘输入,输出最大值及一种划分方式。

输入格式
第一行一个正整数T(T<=10000),表示有T组数据。

接下来T行每行两个正整数N,M。

输出格式
对于每组数据

第一行输出最大值。

第二行输出划分方案,将N按顺序分成M个数输出,两个数之间用空格格开。

样例
样例输入
1
199 2
样例输出
171
19 9

一定要注意输出换行

错误

image
错误数据 in 30 2
ans 3 0
me 0 30
image
因为其结果仍为0 所以若为if(dp[k][b-1]*f[k+1][a]>dp[a][b]) ahead将不被赋值 即输出 0 30
解决方法 改为>=

不用递归就是好啊 虽然结构体套的很乱
image
内存的数字很熟悉

#include<bits/stdc++.h>
using namespace std;
long long t,dp[25][25],f[25][25];//dp i j为前i个数分成j段的最大值 f i j i到j的值 
long long ans[25];
struct str1{
	long long n,m;
	long long num[25],ahead[25][25];
	long long count1; 
}w[10005];
void before(int i);
void ddpp(int i);
void output(int i);
int main (){
	//freopen("test1.in","r",stdin);
	//freopen("test.out","w",stdout);
	cin>>t;
	for(int i=1;i<=t;i++){
		before(i);
		ddpp(i);
		output(i);
		for(int i=1;i<=24;i++){
			for(int j=1;j<=24;j++){
				dp[i][j]=f[i][j]=0;
			}
		} 
	}
	return 0;
} 
void before(int i){
	cin>>w[i].n>>w[i].m;
	while(w[i].n){
		w[i].num[++w[i].count1]=w[i].n%10;
		//cout<<"!!!"<<w[i].num[w[i].count1]<<endl;
		w[i].n/=10;
	}
	for(int ii=1;ii<=w[i].count1;ii++){
		f[ii][ii]=w[i].num[w[i].count1-ii+1];
		for(int jj=ii+1;jj<=w[i].count1;jj++){
			f[ii][jj]=f[ii][jj-1]*10+w[i].num[w[i].count1-jj+1];
		}
	}
	/*for(int ii=1;ii<=w[i].count1;ii++){
		for(int jj=1;jj<=w[i].count1;jj++){
			cout<<setw(10)<<f[ii][jj]<<" ";
		}
		cout<<endl;
	}*/
		
}
void ddpp(int i){
	for(int ii=1;ii<=w[i].count1;ii++){
		dp[ii][1]=f[1][ii];
	}
	for(int b=2;b<=w[i].m;b++){
		for(int a=1;a<=w[i].count1;a++){
			//cout<<"###"<<a<<" "<<b<<endl;
			for(int k=1;k<a;k++){
				//cout<<"!"<<dp[k][b-1]<<" "<<f[k+1][a]<<endl;
				if(dp[k][b-1]*f[k+1][a]>=dp[a][b]){
					dp[a][b]=dp[k][b-1]*f[k+1][a];//dp[a][b]=max(dp[k][b-1]*f[k+1][a],dp[a][b]);
					//cout<<"@@@"<<k<<endl;
					w[i].ahead[a][b]=k;
				}
			}
		}
	}
}
void output(int i){
	int start=w[i].count1;
	int countt=0;
	cout<<dp[w[i].count1][w[i].m]<<endl;
	for(int ii=w[i].m;ii>=1;ii--){
		//cout<<ii<<" "<<start<<"!!!"<<w[i].ahead[start][ii]<<" "<<f[w[i].ahead[start][ii]+1][start]<<endl;
		ans[++countt]=f[w[i].ahead[start][ii]+1][start];
		start=w[i].ahead[start][ii];
	}
	for(int ii=countt;ii>=1;ii--){
		cout<<ans[ii]<<" ";
	}
	cout<<endl;
}

是在乘积最大的基础上做出来的
乘积最大代码

#include<bits/stdc++.h>
using namespace std;
long long n,k,num[45],f[45][45],dp[45][45];//dp i j 为前i个数有j个加号的最大值 
char numm[45];
int main (){
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>numm[i];
		num[i]=numm[i]-48;
	}
	for(int i=1;i<=n;i++){
		f[i][i]=num[i];
		for(int j=i+1;j<=n;j++){
			f[i][j]=f[i][j-1]*10+num[j];
		}
	}
	for(int i=1;i<=n;i++){
		dp[i][0]=f[1][i];
		//dp[i][0]=num[i];好像赋错了 
	}//要赋初值 else 怎么乘都是0 
	/*for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cout<<setw(4)<<f[i][j]<<" ";
		}
		cout<<endl;
	}*/ 
	for(int j=1;j<=k;j++){//j个乘号 
		for(int i=1;i<=n;i++){//前i个数 
			//cout<<i<<" "<<j<<endl;	
			for(int k=1;k<i;k++){
			//	cout<<k<<" "<<dp[k][j-1]<<" "<<f[k+1][i]<<endl; 
				dp[i][j]=max(dp[k][j-1]*f[k+1][i],dp[i][j]);//用前半段乘积最大 填加乘号乘定值 
			}
			//cout<<"!!!"<<dp[i][j]<<endl; 
		}
	}
	cout<<dp[n][k]; 
	return 0;
}
//好像背包dp欸 

原文链接: https://www.cnblogs.com/WANG-Yi-ding/p/15771848.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    整数划分+乘积最大

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/183845

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月12日 上午10:27
下一篇 2023年2月12日 上午10:28

相关推荐