NYOJ 石子合并(一)(区间DP)
题目链接:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=737
题目大意:
有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。
解题思路:
设dp[i][j]为合并完[i,j]区间所有石子的最小花费,sum[i]是1~i对石子价值的前缀和。
得到状态转移方程:dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[i]+sum[i]-sum[j-1]),(i=<k<j)
代码
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=3e2+5; 7 8 int a[N],sum[N],dp[N][N]; 9 10 int main(){ 11 int n; 12 while(~scanf("%d",&n)){ 13 memset(dp,0x3f,sizeof(dp)); 14 for(int i=1;i<=n;i++){ 15 scanf("%d",&a[i]); 16 dp[i][i]=0; 17 sum[i]=a[i]+sum[i-1]; 18 } 19 for(int len=1;len<n;len++){ 20 for(int i=1;i+len<=n;i++){ 21 int j=i+len; 22 for(int k=i;k<j;k++){ 23 int tmp=sum[j]-sum[i-1]; 24 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+tmp); 25 } 26 } 27 } 28 printf("%d\n",dp[1][n]); 29 } 30 return 0; 31 }
#include<iostream>02.#include<cstdio>03.#include<cstring>04.#include<algorithm>05.using namespace std;06.const int N=3e2+5;07. 08.int a[N],sum[N],dp[N][N];09. 10.int main(){11.int n;12.while(~scanf("%d",&n)){13.memset(dp,0x3f,sizeof(dp));14.for(int i=1;i<=n;i++){15.scanf("%d",&a[i]);16.dp[i][i]=0;17.sum[i]=a[i]+sum[i-1];18.}19.for(int len=1;len<n;len++){20.for(int i=1;i+len<=n;i++){21.int j=i+len;22.for(int k=i;k<j;k++){23.int tmp=sum[j]-sum[i-1];24.dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+tmp);25.}26.}27.}28.printf("%d\n",dp[1][n]);29.}30.return 0;31.}

浙公网安备 33010602011771号