【NOI1995】石子合并

区间动态规划的经典题,关于区间dp,状态定义是很显然的,定义f[i][j]表示把i~j这一区间合并花费的最小值,若i=j,则f[i][j]=0,若i≠j,则在i,j当中必定有一点k,使得i,j的区间先合并成i,k和k+1,j,然后合并成i,j.因此,对于每一对i,j,我们都枚举k,那么f[i][j]=min(f[i][k]+f[k+1][j]).然后我们预处理出合并的花费,相加即可。

另外,我们在循环的时候一定要注意阶段,状态,决策三者从外到内循环。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 int sum[310],f[310][310],n;
 6 int main() {
 7     cin>>n;
 8     memset(f,0x3f,sizeof(f));
 9     for(int i=1,x;i<=n;i++) {
10         cin>>x;
11         f[i][i]=0;
12         sum[i]=sum[i-1]+x;
13     }
14     for(int i=2;i<=n;i++) {
15         for(int l=1;l<=n-i+1;l++) {
16             int r=l+i-1;
17             for(int k=l;k<r;k++)
18                 f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]);
19             f[l][r]+=sum[r]-sum[l-1];
20         }
21     }
22     cout<<f[1][n]<<endl;
23     return 0;
24 }
AC Code
原文地址:https://www.cnblogs.com/shl-blog/p/10664295.html