剛開始,想到的是貪心,每次合併相鄰和值最小的兩堆就行了,這題和poj 3186 treats for the cows以及紫書上的「最優矩陣鏈乘」差不多,初看看似貪心,實則是dp問題,但是都不會,呵呵。。。。只能看別人的**,然後再寫。。。
思路:用dp[i][j]表示合併區間[i,j]所需要的最小代價,那麼,狀態轉移方程為:dp[i][j]=max(dp[i]k]+dp[k+1][j]+sum[i][j]),i<=k<=j。顯然,對於我來講,這個式子是不好直接實現遞推的,但是發現這個遞推式子和紫書上的最優矩陣鏈乘差不多,都表示:要求大區間的解,得先知道小區間的解,所以,可以把上述狀態進行轉換一下:用dp[i][j]表示,以i為起點,長度為j的解,則狀態轉移方程變為:dp[i][j]=min(dp[i][j],dp[i][k]+dp[i+k+1][j-k-1]+sum[i][i+j]);這樣一來,就好實現遞推方程了。
**:#include#include#define maxn 110
#define inf 0x7fffffff
using namespace std;
int n,a[maxn],dp[maxn][maxn],sum[maxn];
int main(){
//freopen("in.txt","r",stdin);
int t;cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",a+i);
sum[0]=0;
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+a[i];
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dp[i][j]=inf;//初始化
for(int i=1;i<=n;i++) dp[i][0]=0;//初始化
for(int j=1;j
動態規劃 CSU 1592 石子歸併
題目 現在有n堆石子,第i堆有ai個石子。現在要把這些石子合併成一堆,每次只能合併相鄰兩個,每次合併的代價是兩堆石子的總石子數。求合併所有石子的最小代價。第一行包含乙個整數t t 50 表示資料組數。每組資料第一行包含乙個整數n 2 n 100 表示石子的堆數。第二行包含n個正整數ai ai 100...
CSU 1592 石子歸併 區間dp
現在有n堆石子,第i堆有ai個石子。現在要把這些石子合併成一堆,每次只能合併相鄰兩個,每次合併的代價是兩堆石子的總石子數。求合併所有石子的最小代價。第一行包含乙個整數t t 50 表示資料組數。每組資料第一行包含乙個整數n 2 n 100 表示石子的堆數。第二行包含n個正整數ai ai 100 表示...
石子歸併 CSU 1592 (區間合併)
題意 將n堆石子合併成一堆,每次只能合併相鄰的兩堆石子,每次合併的代價是兩堆石子總石子數和 思路 入門的一道區間dp,將合併區間由小向大推 dp i j 表示合併區間 i,j 的最小代價 初始化dp為inf,dp i i 0 dp i j min dp i k dp k 1 j sum i j i ...