蒟蒻吃药计划-治疗系列 #round 2 合并石子+乘积最大
1.合并石子
《信息學奧賽一本通》第五版 P371 第三節 T1
我就直接開始講吧:
Warning:這個題目和 合并果子 不一樣!不一樣!不一樣!不一樣!不一樣!不一樣!不一樣!不一樣!
:我想告訴你一個事情,你幫幫我好么?
(內心:mmp怎么又是這個人)
:昨天我去商場的時候,錢包被偷了,銀行卡啥的都沒了,你能幫幫我么?
(內心:憑啥,我就不幫)
:如果你幫我找到的話,我給你50金幣好不好?
(*聽到這句話,你充滿了決心)
好吧,那我們幫幫他吧,讓我們先看看他遇到了什么問題
:那個小偷在我的錢包里留了一張紙條,上面寫著一個地址,我昨天到那里去之后看到那兒有幾堆石頭,上面都有數字,旁邊有一塊石碑,要我把相鄰的兩對合并,最后只剩一堆,讓花費的體力最小
體力是怎么計算的呢?
:兩堆石子合并之后,花費的體力值為兩堆石頭上的數字的和
好,那我們先和他告別,自己想一想
他已經告訴我們,有 N 堆石子,每堆石子都有對應的一個數字
我們就開一個 stone 數組表示吧
不過要說明一點,為了表示方便,我們把 stone[i] 表示為前 i 堆石子的和
我們再開一個 giver 二維數組,并且讓 giver[i][j] 表示為第 i 堆到第 j 堆的石子合并之后花費的最小體力值
那么,我們應該怎么去求得花費最小的體力值呢?
讓我們仔細思索一下
先開個循環吧
設有一 i 并使得 i=n-1...1?作為左端點
再設一 j 使得 j=i+1...n 作為右端點
可是這樣好像還不夠
那我們再弄一個 k 并讓 k=i...j-1?把 i 開頭 j 結尾的 giver[i][j] 分成兩段
用 k 枚舉每一種可能的分段,一步一步推出正確答案!
根據上面的東西,我們就可以推出狀態轉移方程:
giver[i][j]=min(giver[i][j],giver[i][k]+giver[k+1][j]+stone[j]-stone[i-1]);
對啦!
邊界條件:
giver[1...n][1...n]=0;
現在,讓我們帶著這兩個小朋友開始破譯這個問題吧!
代碼如下:
1 #include <bits/stdc++.h> 2 #define fp(i,l,r) for(register int i=(l);i<=(r);++i) 3 #define fd(i,l,r) for(register int i=(l);i>=(r);--i) 4 using namespace std; 5 inline int botposs(int a,int b,int pd){ 6 if(pd==1) return a>b?a:b; 7 if(pd==0) return a>b?b:a; 8 } 9 int main(){ 10 int n; 11 int stone[100+20]={0}; 12 int giver[100+20][100+20]; 13 memset(giver,32,sizeof(giver)); 14 stone[0]=0; 15 scanf("%d",&n); 16 fp(i,1,n){ 17 int x; 18 scanf("%d",&x); 19 stone[i]=stone[i-1]+x; 20 } 21 fp(i,1,n){ 22 giver[i][i]=0; 23 } 24 fd(i,n-1,1){ 25 fp(j,i+1,n){ 26 fp(k,i,j-1){ 27 giver[i][j]=botposs(giver[i][j],giver[i][k]+giver[k+1][j]+stone[j]-stone[i-1],0); 28 } 29 } 30 } 31 printf("%d",giver[1][n]); 32 return 0; 33 }合并石子
現在我們去找他吧!
他成功了嗎?
:成是成功了,錢包也找回來了,可是解開這個謎題之后,突然出現了一個山洞,里面有一個房間,烏七八黑的,我不敢進去,你再幫幫我好嗎?如果成功,我給你100金幣
(*你充滿了決心)
好吧,我們就再答應他一次吧!為了我們的金幣!
?2.乘積最大
《信息學奧賽一本通》第五版 P371 第三節 T2
:你好啊,昨天我感冒了,對,就是那種,最新的,恩恩,對對對
這個家伙怎么了?這才一個晚上呢,怎么就感冒了?
:哦,可能是昨天空調開太大了,然后踢了被子,就著涼了吧
...
:對了,我們去山洞那兒吧
我們走吧
:咦,怎么到處都是警……阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿阿嚏
看樣子他咳得很嚴重啊,不過我們還是得先想辦法進去,這兒全都是警察...
那我們作弊吧,花費20金幣進去( - MDZZ還能這么玩? - 我有錢我是RMB玩家你咬我啊略略略略略)
好的,現在我們進來了,現在我們眼前有一張書桌,上面趴著一個人,手里有一支帶有血跡的筆,桌子上到處都是凝固了的血液
:(loudly)哇,好可怕好血腥啊............
拜托啊你少說點話啊,被警察發現就完蛋了啊!
:(very loudly)啊?什么?
......那我們先捂住他的嘴,等警察走了之后,自己去看看
越過封鎖線,我們來到書桌前,觀察一下吧,加點Exp
咦?這支筆怎么像脫節了一樣啊?
讓我們拆開,里面有一張卷曲的紙片,上面寫著幾行字
我們了解一下大意啊,恩,應該就是說:
給你k個乘號,讓你插入一個數,使得插入之后的各個數乘積最大,保證乘號的數量比數字的位數少起碼兩個
恩........................................................................................................................................
我想這道題應該可以用動態規劃來完成
我們將$k$個乘號視為$k$個階段
我們先設一$num$數組并且用$num[j][i]$表示第$j$位到第$i$位的所組成的自然數
按照套路,我們搞一個$dp$數組并且得到狀態轉移方程$dp[i][j]=max{dp[j][k-1]*num[j+1][i]}(k<=j<i)$
不過,代碼實現時的方程應該是這樣的$dp[i][k]=max(dp[i][k],dp[j][k-1]*num[j+1][i])$
加上一個邊界條件$dp[j][0]=num[1][j](1<=j<=n)$
最后的代碼就不放出來啦!
:唔......
啊,我們忘記他了!
他指不準又弄出了什么幺蛾子,反正100金幣已經到手了,去看看吧!
?
轉載于:https://www.cnblogs.com/Fraction/p/8413340.html
總結
以上是生活随笔為你收集整理的蒟蒻吃药计划-治疗系列 #round 2 合并石子+乘积最大的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 手机已经贴了防爆膜了,可以再贴钢化膜吗,
- 下一篇: html知识点回顾
