【思路】
我们 dp[i][j] 来表示合并第 i 堆到第 j 堆石子的最小代价。
那么状态转移方程为 dp[i][j] = min ( dp[i][j],dp[i][k]+dp[k+1][j]+w[i][j]);
其中, w[i][j] 表示把两部分合并起来的代价,即从第 i 堆到第 j 堆石子个数的和,为了方便查询,我们可以用 sum[i] 表示从第1堆到第i堆的石子个数和,那么 w[i][j]=sum[j]-sum[i-1].(前缀和思想)
AC_Code:
1 #include <bits/stdc++.h> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <cmath> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <set> 10 #include <map> 11 #include <algorithm> 12 using namespace std; 13 typedef long long ll; 14 const int maxn=205; 15 const ll mod=1e9+7; 16 const ll INF=1e18; 17 const double eps = 1e-9; 18 19 int n,x; 20 int sum[maxn]; 21 int dp[maxn][maxn];///合并第i堆到第j堆石子的最小代价 22 int main() 23 { 24 while(~scanf("%d",&n)){ 25 sum[0]=0; 26 memset(dp,0x3f,sizeof(dp)); 27 for(int i=1;i<=n;i++){ 28 scanf("%d",&x); 29 sum[i]=sum[i-1]+x; 30 dp[i][i]=0; 31 } 32 for(int len=2;len<=n;len++){ 33 for(int i=1;i<=n;i++){ 34 int j=i+len-1; 35 if( j>n ) continue; 36 for(int k=i;k<j;k++){ 37 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+(sum[j]-sum[i-1])); 38 } 39 } 40 } 41 printf("%d ",dp[1][n]); 42 } 43 return 0; 44 }
【平行四边形优化】:详解
1 #include <bits/stdc++.h> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <cmath> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <set> 10 #include <map> 11 #include <algorithm> 12 using namespace std; 13 typedef long long ll; 14 const int maxn=205; 15 const ll mod=1e9+7; 16 const ll INF=1e18; 17 const double eps = 1e-9; 18 19 int n,x; 20 int sum[maxn]; 21 int dp[maxn][maxn];///合并第i堆到第j堆石子的最小代价 22 int s[maxn][maxn]; 23 int main() 24 { 25 while(~scanf("%d",&n)){ 26 sum[0]=0; 27 memset(dp,0x3f,sizeof(dp)); 28 for(int i=1;i<=n;i++){ 29 scanf("%d",&x); 30 sum[i]=sum[i-1]+x; 31 dp[i][i]=0; 32 s[i][i]=i; 33 } 34 for(int len=2;len<=n;len++){ 35 for(int i=1;i<=n;i++){ 36 int j=i+len-1; 37 if( j>n ){ 38 continue; 39 } 40 for(int k=s[i][j-1];k<=s[i+1][j];k++){ 41 if( dp[i][k]+dp[k+1][j]+(sum[j]-sum[i-1])<dp[i][j] ){ 42 dp[i][j]=dp[i][k]+dp[k+1][j]+(sum[j]-sum[i-1]); 43 s[i][j]=k; 44 } 45 } 46 } 47 } 48 printf("%d ",dp[1][n]); 49 } 50 return 0; 51 }