codevs 1048 石子归并

来源:互联网 发布:云计算解决方案架构师 编辑:程序博客网 时间:2024/06/05 07:52

有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1]。问安排怎样的合并顺序,能够使得总合并代价达到最小。

dp[i][j]表示从j堆开始合并,i堆石子合并为一堆
dp[i][j] = min{dp[i - 1][j] + dp[1][i + j - 1],dp[i - 2][j] + dp[2][i + j - 2]….}
即 dp[i][j] = min{dp[i - k][j] + dp[k][i + j - k]};

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 1e6 + 10;int dp[150][150],a,n,sum[150];int main(){    scanf("%d",&n);    for(int i = 1; i <= n; ++i)    {        scanf("%d",&a);        sum[i] = sum[i - 1] + a;     }     for(int i = 2; i <= n; ++i)    {        for(int j = 1; j <= n - i + 1; ++j)        {            dp[i][j] = 0x3f3f3f3f;            for(int k = 1; k < i; ++k)            {                dp[i][j] = min(dp[i - k][j] + dp[k][i + j - k] + sum[i + j - 1] - sum[j - 1],dp[i][j]);            }        }    }    printf("%d",dp[n][1]);    return 0;}

可以用滚动数组

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 1e6 + 10;int ans = 1e-9,dp[3],a,n;int main(){    scanf("%d",&n);    for(int i = 1; i <= n; ++i)    {        scanf("%d",&a);        dp[(i % 2)] = max(dp[(i - 1) % 2] + a,a);        ans = max(dp[(i % 2)],ans);    }     printf("%d",ans);    return 0;} 
原创粉丝点击