codevs 石子歸併

區間 dp 尋找狀態轉移方程 dp[i][j]=min(dp[i][k]+dp[k+1][j]+s[j]-s[i-1]);

其實 剛開始我也不知道爲啥 就是做着做着就習慣了 ,不信你試試 一個月後 你會發現一切都水到渠成 。









1048 石子歸併

時間限制: 1 s
空間限制: 128000 KB
題目等級 : 黃金 Gold
題目描述 Description

有n堆石子排成一列,每堆石子有一個重量w[i], 每次合並可以合併相鄰的兩堆石子,一次合併的代價爲兩堆石子的重量和w[i]+w[i+1]。問安排怎樣的合併順序,能夠使得總合並代價達到最小。

輸入描述 Input Description

第一行一個整數n(n<=100)

第二行n個整數w1,w2...wn  (wi <= 100)

輸出描述 Output Description

一個整數表示最小合併代價

樣例輸入 Sample Input

4

4 1 1 4

樣例輸出 Sample Output

18

數據範圍及提示 Data Size & Hint


#include <bits/stdc++.h>
using namespace std;
typedef long long ll ;
typedef double    dl ;
#define INF 0x7f
const int maxn =1e2+5; 
const int mod = 1000000007;  
#define f(i,l,r) for(int i=l;i<=r;++i)
#define g(i,l,r) for(int i=l;i>=r;--i)
#define inf 214748364
int a[maxn],sum[maxn];
int dp[maxn][maxn]; 
int n;
void slove()
{

 	f(len,1,n-1)
 	{ 
 		for(int i=1,j=len+1;j<=n;j++,i++)
 		{
 			dp[i][j]=inf;
			f(s,i,j-1)
			 dp[i][j]=min(dp[i][j],dp[i][s]+dp[s + 1][j] + sum[j] - sum[i - 1]);

 		}
 	}
	 
 	cout<<dp[1][n]<<endl;		 
}
 

int main()
{
     
    freopen("in","r",stdin);
  
    cin>>n;
    f(i,1,n)
    {
    	cin>>a[i];
    	sum[i]=sum[i-1]+a[i];
    }
   	slove();
 

    return 0; 
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章