[藍橋杯] 乘積最大(dfs或dp)
題目連結:https://www.dotcpp.com/oj/problem1602.html
題目描述
今年是國際數學聯盟確定的“2000——世界數學年”,又恰逢我國著名數學家華羅庚先生誕辰90週年。在華羅庚先生的家鄉江蘇金壇,組織了一場別開生面的數學智力競賽的活動,你的一個好朋友XZ也有幸得以參加。活動中,主持人給所有參加活動的選手出了這樣一道題目:
設有一個長度為N的數字串,要求選手使用K個乘號將它分成K+1個部分,找出一種分法,使得這K+1個部分的乘積能夠為最大。
同時,為了幫助選手能夠正確理解題意,主持人還舉了如下的一個例子:
有一個數字串:312, 當N=3,K=1時會有以下兩種分法:
3 * 12=36
31 * 2=62
這時,符合題目要求的結果是:31*2=62
現在,請你幫助你的好朋友XZ設計一個程式,求得正確的答案。
輸入
程式的輸入共有兩行:
第一行共有2個自然數N,K(6≤N≤40,1≤K≤6)
第二行是一個長度為N的數字串。
輸出
輸出所求得的最大乘積(一個自然數)。
樣例輸入
4 2
1231
樣例輸出
62
dfs需要傳入三個變數:值的大小 遍歷到那個位置 乘號用的數量
dfs程式碼:
#include<cstdio>
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
int n,k;
char mp[100];
int a[100];
int mx;
void dfs(int sum,int len,int num)///當前的乘積sum 遍歷到的位置len 使用的乘號的數量num
{
if(len>n)
return;
if(num>k)
return;
if(num==k)
{
int res=0;
for(int i=len+1; i<=n; i++)
res=res*10+a[i];
sum*=res;
mx=max(mx,sum);
return;
}
for(int i=1; i<=n-len; i++) ///還可以分成的長度
{
int res=0;
for(int j=len+1; j<=len+i&&j!=n; j++)
res=res*10+a[j];
dfs(sum*res,len+i,num+1);
}
return;
}
int main()
{
mx=0;
scanf("%d%d",&n,&k);///字串的數量 乘號的數量
scanf("%s",mp);
int i=0;
while(mp[i]!='\0')
{
a[i+1]=mp[i]-'0';
i++;
}
dfs(1,0,0);///乘積*1
printf("%d\n",mx);
return 0;
}
dp思路:
dp[i][j]: 在長度為i的字串裡插入j個乘號,所得的乘積最大值為多少。
最終的答案就是dp[n][m]
狀態轉移方程: dp[i][j]=max{dp[k][j-1]*sum} k<i
dp[k][j-1] 表示長度為k的字串,插入j-1個乘號時它的乘積最大值為dp[k][j-1]
sum表示k到i這段字串表示的數字,也就是剩下的那部分字串的大小
舉例:
12345這個字串插入兩個乘號的最大乘積,也就是dp[4][2]為多少
那你要考慮,max{ dp[1][1] ,dp[2][1] ,dp[3][1] dp[4][1]} * sum
dp[1][1]sum表示 dp[1][1]乘2345
dp[2][1]sum表示 dp[2][1]乘345
dp[3][1]sum表示 dp[3][1]乘45
dp[4][1]sum表示dp[4][1]乘5
完整程式碼:
#include<cstdio>
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
int n,k;
char mp[100];
int a[100];
int dp[50][10];///dp[i][j]:前i個字元放j個乘號
int solve(int l,int r)
{
int sum=0;
for(int i=l; i<=r; i++)
sum=sum*10+a[i];
return sum;
}
int main()
{
scanf("%d%d",&n,&k);///字串的數量 乘號的數量
scanf("%s",mp);
int i=0;
while(mp[i]!='\0')
{
a[i+1]=mp[i]-'0';
i++;
}
memset(dp,0,sizeof(dp));
for(int i=0; i<=n; i++)
dp[i][0]=solve(1,i);
for(int i=1; i<=n; i++)
for(int j=1; j<=k&&j<=i-1; j++)///前i個字元最多可以放i-1個乘號
for(int m=1; m<i; m++)
dp[i][j]=max(dp[i][j],dp[m][j-1]*solve(m+1,i));
printf("%d\n",dp[n][k]);
return 0;
}
相關文章
- 第九屆藍橋杯B組省賽———乘積最大
- 藍橋杯刷題-乘積尾零
- [藍橋杯2018決賽]最大乘積
- 藍橋杯-迷宮(BFS+DFS)
- 【DP】乘積最大子陣列陣列
- [藍橋杯][演算法提高VIP]最大乘積 貪心 雙指標演算法指標
- 藍橋杯2015初賽生命之樹 DFS圖解圖解
- 藍橋杯
- [藍橋杯][演算法提高VIP]奪寶奇兵 dp演算法
- 藍橋杯 演算法提高 拿糖果(完全揹包dp)演算法
- P8675 [藍橋杯 2018 國 B] 搭積木
- [藍橋杯][基礎練習VIP]矩形面積交
- P8792 [藍橋杯 2022 國 A] 最大公約數
- 藍橋杯 買瓜
- 藍橋杯-分巧克力
- 藍橋杯-N皇后
- 藍橋杯真題
- 藍橋杯 剪格子
- 第九屆藍橋杯省賽C++A組 倍數問題(dfs)C++
- 藍橋杯-長草(BFS)
- 藍橋杯-螞蟻感冒
- 藍橋杯-帶分數
- 藍橋杯-翻硬幣
- 藍橋杯-座次問題
- 藍橋杯-日期問題
- 藍橋杯 計算方程
- 藍橋杯-排列序數
- 如何準備藍橋杯
- 藍橋杯年號字串字串
- 藍橋杯考點整理
- 藍橋杯 分巧克力(Java)Java
- 藍橋杯訓練2
- 藍橋杯 整數拼接
- 藍橋杯注意的地方
- E62 樹形DP P8677 [藍橋杯 2018 國 A] 採油
- 藍橋杯學習路線
- 藍橋杯——查詢的妙趣
- 藍橋杯——巧妙地遞迴遞迴