一道非常好的DP,菜狗子多做這種題

2021-07-31 04:15:00 字數 1624 閱讀 5059

題目描述

今年是國際數學聯盟確定的「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<=30)

第二行是乙個長度為n的數字串。

輸出格式

相對於輸入,應輸出所求得的最大乘積(乙個自然數)。

樣例輸入:

4 21231

樣例輸出:6 2

這道題和我之前做過的一道hihocoder非常類似,我在做這道題的時候想到的是搜尋,說實話,我壓根就沒有想到用dp,這實在是乙個悲傷的故事。持續更新我還是乙個菜鳥,我的dp還是一如既往的菜。

這道題為什麼可以用dp呢?因為這明顯具有子問題,並且具備記憶化搜尋的特徵,至於dp的其他特徵我是真沒看出來。好了,那麼這道題的關鍵就出來了,我們該如何dp?假設我們設dp[i][j]表示在1-i中插入j個乘號的最大值,那麼dp[n][k]就是這道題的答案。看起來非常簡單,但問題出來了,狀態轉移方程呢?dp[i][j]不再是普通的和dp[i-1][j]或者dp[i-1][j-1]有聯絡,他還和dp[i-k][j-1]也有聯絡(這裡的k的範圍要注意,我會在**中給出解釋)。

[cpp]view plain

copy

#include

#define ll long long

using

namespace

std;  

ll num[50][50];  

ll dp[50][50];  

string s;  

intn,k;  

intmain()  

}  for(i=0;i

dp[i][0]=num[0][i];     //這裡對於dp陣列的初始化非常重要 

for(i=0;i

}  }  printf("%lld\n"

,dp[n-1][k]);  

return

0;  

}  下面是網上乙個人寫的三維的dp,看起來比我這個要高大上,不過他的**過不了最後乙個測試點,我給他在輸出的時候改了一下判斷條件就過了。

#include #include #include using namespace std;  

int n,k;

char a[50];

long long num[50][50];

long long dp[50][50][10];

int main()

乙個講的非常好的快速排序

講的非常好,反正我是看懂了 package com.shadow.util 快速排序的乙個實現 author shadow public class myquicksort 一次查詢後,將基準數歸位 arr left arr i arr i pivot 繼續處理左邊的,這裡是乙個遞迴的過程 quic...

乙個非常好的ORACLE的分頁SQL語句

select from select my table.rownum as my rownum from select yhbh,yhmc from yysf tb yonghxx order by yhbh my table where rownum 20 where my rownum 10 其...

Oracle 的乙個非常好的觸發器例子

create orreplace trigger test trigger after insert orupdate of sal or delete onemp foreach row begin case when inserting then 當事件為insert時,inserting為tr...