1. 程式人生 > 其它 >NOJ---數字串乘積最大(dp)

NOJ---數字串乘積最大(dp)

連結: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的戀戀不捨。