首页 > 其他 > 详细

区间dp(入门题)

时间:2019-03-27 22:22:09      阅读:188      评论:0      收藏:0      [点我收藏+]

(持续更新)

区间dp:顾名思义就是在区间上进行动态规划,通过合并小区间求解一段区间上的最优解。

常见模板:

for(int len=1;len<n;len++){//区间长度 
		for(int be=1;be+len<=n;be++){//起点 
			int en=be+len;//终点 
			for(int j=be;j<en;j++){//割点 
				dp[be][en]=min(dp[be][en],dp[be][j]+dp[j+1][en]+割点代价);
			}
		}
	}

  

http://www.51nod.com/Challenge/Problem.html#!#problemId=1021

1021 石子归并

 
N堆石子摆成一条线。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的代价。计算将N堆石子合并成一堆的最小代价。
 
例如: 1 2 3 4,有不少合并方法
1 2 3 4 => 3 3 4(3) => 6 4(9) => 10(19)
1 2 3 4 => 1 5 4(5) => 1 9(14) => 10(24)
1 2 3 4 => 1 2 7(7) => 3 7(10) => 10(20)
 
括号里面为总代价可以看出,第一种方法的代价最低,现在给出n堆石子的数量,计算最小合并代价。
 

输入

第1行:N(2 <= N <= 100)
第2 - N + 1:N堆石子的数量(1 <= A[i] <= 10000)

输出

输出最小合并代价

输入样例

4
1
2
3
4

输出样例

19
解题思路:很明显割点代价为前缀和:sum【en】-sum【be-1】//en为该区间的终点,be为起点
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<stack>
#include<cstdio>
#include<map>
#include<set>
#include<string>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
#define ri register int
typedef long long ll;

inline ll gcd(ll i,ll j){
	return j==0?i:gcd(j,i%j);
}
inline ll lcm(ll i,ll j){
	return i/gcd(i,j)*j;
}
inline void output(int x){
	if(x==0){putchar(48);return;}
	int len=0,dg[20];
	while(x>0){dg[++len]=x%10;x/=10;}
	for(int i=len;i>=1;i--)putchar(dg[i]+48);
}
inline void read(int &x){
    char ch=x=0;
    int f=1;
    while(!isdigit(ch)){
    	ch=getchar();
		if(ch==‘-‘){
			f=-1;
		}	
	}
    while(isdigit(ch))
        x=x*10+ch-‘0‘,ch=getchar();
        x=x*f;
}
const int maxn=105;
ll dp[maxn][maxn];
ll sum[maxn];
ll a[maxn];
int main(){
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%lld",&a[i]);
		sum[i+1]=sum[i]+a[i];
	}
	for(int i=0;i<maxn;i++){
		for(int j=0;j<maxn;j++){
			dp[i][j]=1e18;
		}
	}
	for(int i=0;i<maxn;i++){
		dp[i][i]=0;
	}
	for(int len=1;len<n;len++){//区间长度 
		for(int be=1;be+len<=n;be++){//起点 
			int en=be+len;//终点 
			for(int j=be;j<en;j++){//割点 
				dp[be][en]=min(dp[be][en],dp[be][j]+dp[j+1][en]+sum[en]-sum[be-1]);
			}
		}
	}
	cout<<dp[1][n];
	return 0;
}

  

区间dp(入门题)

原文:https://www.cnblogs.com/Zhi-71/p/10611042.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!