ZJU1602 區間DP記憶化搜尋解法

2021-08-01 12:40:21 字數 1477 閱讀 4509

中文大意:

乘法遊戲是在一行牌上進行的。每一張牌包括了乙個正整數。在每乙個移動中,玩家拿出一張牌,得分是用它的數字乘以它左邊和右邊的數,所以不允許拿第1張和最後1張牌。最後一次移動後,這裡只剩下兩張牌。

目標是使得分的和最小。

例如,如果數是10 1 50 20 5,依次拿1、20、50,總分是10*1*50+50*20*5+10*50*5=8000

而拿50、20、1,總分是1*50*20+1*20*5+10*1*5=1150。

輸入第一行包括牌數(3<=n<=100),第二行包括n個1-100的整數,用空格分開。

處理到檔案結束。輸出每一組資料一行:最小得分樣例輸入

610 1 50 50 20 5

樣例輸出

3650

題目解法:

當我們從最後一步去倒推的時候就可以發現,比如最後乙個拿走1,這一列數可以得到的最小分數是10*1*5+拿走1到5的總分+拿走10到1的總分。這與你如何拿走1到5和拿走10到1沒有關係,符合dp的無後效性。於是,我們可以根據此寫出dp的遞推式:

f[i,j]=min+card[i]*card[k]*card[j]

(i其中f[i,j]表示拿走第i張牌與第j張牌之間的牌最小的得分,card[i]表示的i張牌的分數。我們通過列舉最後乙個拿走的牌k就可以求出f[i,j]的最小值。最後答案為f[1,n]。

懂題意後記憶化搜尋的方法比較容易思考,畢竟這個需要考慮步長,不太容易想到遞推寫法。

#includeusing namespace std;

long long dp[103][103];

int card[103];

long long dfs(int i,int j)

for(int i=1;i<=n;i++)

cout<

#include#include#define m 101

using namespace std;

/* 2588443 2011-07-20 22:40:30 accepted 1602 c++ 0 188 ashione

題目解法:

當我們從最後一步去倒推的時候就可以發現,比如最後乙個拿走1,

這一列數可以得到的最小分數是10*1*5+拿走1到5的總分+拿走10到1的總分。

這與你如何拿走1到5和拿走10到1沒有關係,符合dp的無後效性。

於是,我們可以根據此寫出dp的遞推式:

sorce[i][j]=min+card[i]*card[k]*card[j] (i(n-1)遞增。

*/

int main(){

int sorce[m][m],card[m],i,j,k,delta,n;

while(cin>>n){

for(i=1;i<=n;i++)

cin>>card[i];

memset(sorce,0,sizeof(sorce));

for(delta=1;delta

hdu4283區間dp 記憶化搜尋 區間分化

題意 給你一些人的屌絲值di,計算總屌絲值 sum k 1 di k為第i個人進入的位置。給你乙個棧,可以使人的位置改變。方法一 記憶化搜尋 dp i j k 表示區間 i,j 第i個人放在k位置的屌絲值。搜尋所有的狀態,記錄已經搜尋的狀態。記憶化搜尋 這裡也可以用二維的陣列,另外用乙個sum陣列和...

洛谷1880 區間dp 記憶化搜尋 合併石子

題目 題意是 給定乙個序列,最小規則是相鄰兩個值的合併,開銷是他們的和,將整個序列合併成乙個值的情況下,求解該值的最小值和最大值。如下 1 include2 using namespace std 3 typedef unsigned int ui 4 typedef long long ll 5 ...

合併遊戲 737 區間Dp

石子合併 一 時間限制 1000 ms 記憶體限制 65535 kb 難度 3 描述 有n堆石子排成一排,每堆石子有一定的數量。現要將n堆石子並成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過n 1次合併後成為一堆。求出總的代價最小值。輸入 有多組測試資...