整数划分+乘积最大
记得开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
一定要注意输出换行
错误
错误数据 in 30 2
ans 3 0
me 0 30
因为其结果仍为0 所以若为if(dp[k][b-1]*f[k+1][a]>dp[a][b]) ahead将不被赋值 即输出 0 30
解决方法 改为>=
不用递归就是好啊 虽然结构体套的很乱
内存的数字很熟悉
#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欸