UVA - 10003 - Cutting Sticks (区间DP)

UVA - 10003 - Cutting Sticks (区间DP)_第1张图片






这里简述一下区间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 0x3fffffff
using 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;
} 












你可能感兴趣的:(ACM,uva,区间DP)