中文大意:
乘法遊戲是在一行牌上進行的。每一張牌包括了乙個正整數。在每乙個移動中,玩家拿出一張牌,得分是用它的數字乘以它左邊和右邊的數,所以不允許拿第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次合併後成為一堆。求出總的代價最小值。輸入 有多組測試資...