您的位置:首页 > 其它

51nod 1021 石子归并 -动态规划

2017-12-06 17:20 253 查看
题目链接:1021

贪心似乎无法求解。

dp[i][j]代表归并[j,j+i-1]这段区间的花费,归并每次是归并两堆石子,则划分这段区间有i-1种方式,所以dp[i][j]=max(dp[k][j]+dp[i-k][j+k]+sum[i][j]),k∈[1,i-1],其中sum[i][j]是这段区间石子数量和。

然后就是自底向上dp了.

代码:

#include<iostream>
#include<cstring>
#include<climits>
using namespace std;

long long dp[110][110];
long long sum[110][110];

int main(){
long long ans=0;
int n;
cin>>n;
for(int i=1;i<=n;i++)for(int j=0;j<n;j++)dp[i][j]=INT_MAX;
for(int i=0;i<n;i++)cin>>sum[1][i];

//先单独地把个个区间石子数量和单独计算出来
for(int i=2;i<=n;i++){
sum[i][0]=0;
for(int j=0;j<i;j++)sum[i][0]+=sum[1][j];
}
for(int i=2;i<=n;i++){
for(int j=1;j+i<=n;j++){
sum[i][j]=sum[i][j-1]-sum[1][j-1]+sum[1][j+i-1];
}
}

memset(dp[1],0,sizeof(dp[1]));
for(int i=2;i<=n;i++){
for(int j=0;j+i<=n;j++){
for(int k=1;k<i;k++)if(dp[i][j]>dp[k][j]+dp[i-k][j+k]+sum[i][j])dp[i][j]=dp[k][j]+dp[i-k][j+k]+sum[i][j];
}
}

cout<<dp
[0];
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: