您的位置:首页 > 其它

51nod 1021 石子归并(基础dp)

2017-05-10 19:21 369 查看
假设有n堆石子,要把石子有次序的两两合并,要求代价最小。假设1~n之间有一k,把石子分为1~k和k~n两部分,划分后的这两部分再继续这样划分,直到不能划分,然后就开始分别合并,求出合并后的最小代价,即cost[1~n]=min{cost[1~k]+cost[k+1~n] | 1<=k<=n },用记忆化搜索还是比较好写的。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int INF = 0x3f3f3f3f;
const int MAXN = 110;
int num[MAXN];
int sum[MAXN];
int n;
int dp[MAXN][MAXN];

int dfs(int l, int r)
{
if(dp[l][r] > 0)
return dp[l][r];
if(l == r)
return dp[l][r] = 0;
if(l+1 == r)
return dp[l][r] = num[l]+num[r];
dp[l][r] = INF;
for(int k = l; k < r; ++k)
dp[l][r] = min(dp[l][r],dfs(l,k)+dfs(k+1,r)+sum[r]-sum[l-1]);
return dp[l][r];
}

int main()
{
scanf("%d",&n);
for(int i = 1; i <= n; ++i)
{
scanf("%d",&num[i]);
sum[i] = sum[i-1]+num[i];
}
int res = dfs(1,n);
printf("%d\n",res);
return 0;
}


用循环写:

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

const int INF = 0x3f3f3f3f;
const int MAXN = 110;
int dp[MAXN][MAXN];
int num[MAXN],sum[MAXN];
int n;

int main()
{
cin >> n;
for(int i = 1; i <= n; ++i)
{
cin >> num[i];
sum[i] = sum[i-1]+num[i];
}
for(int l = 2; l <= n; ++l)
{
for(int i = 1; i <= n; ++i)
{
int j = i+l-1;
if(j > n) break;
dp[i][j] = INF;
for(int k = i; k < j; ++k)
dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
}
}
cout << dp[1]
<< endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: