NOJ---數字串乘積最大(dp)
阿新 • • 發佈:2021-08-04
連結:https://ac.nowcoder.com/acm/contest/1071/A
來源:牛客網
題目描述
今年是國際數學聯盟確定的“2000——世界數學年”,又恰逢我國著名數學家華羅庚先生誕辰90週年。在華羅庚先生的家鄉江蘇金壇,組織了一場別開生面的數學智力競賽的活動,你的一個好朋友XZ也有幸得以參加。活動中,主持人給所有參加活動的選手出了這樣一道題目:設有一個長度為N的數字串,要求選手使用K個乘號將它分成K+1個部分,找出一種分法,使得這K+1個部分的乘積能夠為最大。
同時,為了幫助選手能夠正確理解題意,主持人還舉了如下的一個例子:
有一個數字串:312, 當N=3,K=1時會有以下兩種分法:
1) 3*12=36
2) 31*2=62
這時,符合題目要求的結果是:31*2=62
現在,請你幫助你的好朋友XZ設計一個程式,求得正確的答案。
輸入描述:
第一行共有2個自然數N,K(6 ≤ N ≤ 40,1 ≤ K ≤ 6)
第二行是一個長度為N的數字串。
輸出描述:
輸出所求得的最大乘積(一個自然數)。
------------------------------分割線-----------------------------------
如:輸入4 2 1231,答案是62,在1、2,2、3,之間分別插一個乘號*。
思路:
1、對字串的初始化,建立二維陣列nums[i][j],表示字串(範圍i~j)對應的數值;
2、建立二維陣列dp[i][j],表示下標為0~i的字串插入j個乘號*時的最大值,注意下標範圍0~i。
程式碼:
#include <iostream>
#include <string>
using namespace std;
const int N = 100;
int n,k;
int dp[N][7];
int nums[N][N];
string str;
int main()
{
ios::sync_with_stdio(false);
cin>>n>>k;
cin>>str;
for (int i = 0; i < n; i++) {
int tmp = 0;
for (int j = i; j < n ; ++j) {
tmp = tmp * 10 + str[j] - 48;
nums[i][j] = tmp;
}
// dp[i][0] = nums[0][i] //等同下面的初始化
}
for (int i = 0; i < n; ++i) { // 遍歷字串
dp[i][0] = nums[0][i];
for (int j = 1; j <= k; j++) { // 插入j個乘號* 時的狀態
for (int x = 0; x < i; ++x) // 在x位置插入一個*時,將0~x和x+1~i分為兩部分相乘
dp[i][j] = max(dp[x][j-1]*nums[x+1][i],dp[i][j]);// 判斷是否插入這個乘號*,注意插入這個*後,下標0~x的字串還剩下j-1個乘號
}
}
cout<<dp[n-1][k]<<endl;
return 0;
}
小tips:其中一句ios::sync_with_stdio(false)是為加快cin,cin將從螢幕輸入的資料緩衝進輸入流,相比scanf會緩慢一些,這也算是c++對c的戀戀不捨。