UVA - 10003 - Cutting Sticks (区间DP)

来源:互联网 发布:手机打卡软件 编辑:程序博客网 时间:2024/05/16 07:34







这里简述一下区间DP:

主要思想:

区间动态规划问题一般都是考虑对于每段区间,他们的最优值都是由几段更小区间的最优值得到,是分治思想的一种应用,将一个区间问题不断划分为更小的区间直至一个素组成的区间,枚举他们的组合,求合并后的最优值。

定义状态:设dp[i][j]为区间i,j之间的最小代价(实际看题意)

实现过程:

for(int p = 1 ; p <= n ; p++) {//p是区间的长度,作为阶段

for(int i = 1 ; i <= n ; i++) {//i是穷举区间的起点

int j = i+p-1;//j为区间的终点

for(int k = i ; k < j ; k++)//状态转移

dp[i][j] = min{dp[i][k]+dp[k+1][j]+w[i][j]};//这个是看题目意思,有的是要从k开始不是k+1

dp[i][j]= max{dp[i][k]+dp[k+1][j]+w[i][j]};

}

}





对于这一题来说:首先得明确状态转移方程为dp[i][j]=min(dp[i][k],dp[k][j])+num[j]-num[i] (i<k<j),且这里k不能等于i和j,因为k代表的是区间i,j之间可以切割的点,显然要切割中间的,不需要切割边上的,所以这里要往外层加一层边界,即区间的最外边,因此有这题答案dp[0][n+1] 代表从最左边到最右边(0最左边n+1最右边)切割木条可以获得的最小值。




AC代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cmath>#define INF 0x3fffffffusing namespace std;const int maxn = 60;int dp[maxn][maxn];//dp[i][j]代表在区间i,j之间的最小代价 int num[maxn];int main() {int L, n;while(scanf("%d", &L) && L) {scanf("%d", &n);for(int i = 1; i <= n; i++) scanf("%d", &num[i]);num[0] = 0;num[n + 1] = L;memset(dp, 0, sizeof(dp));for(int p = 1; p <= n + 1; p++)for(int i = 0; i <= n + 1; i++) {int j = i + p;int MIN = INF;if(j > n + 1) break;for(int k = i + 1; k < j; k++) {int tmp = dp[i][k] + dp[k][j] + num[j] - num[i];MIN = min(MIN, tmp);}if(MIN != INF) dp[i][j] = MIN;}printf("The minimum cutting is %d.\n", dp[0][n + 1]);} return 0;} 












1 0