1.题目描述:点击打开链接
2.解题思路:本题类似于动态规划中的“最优矩阵链相乘”问题——具有最优子结构。定义d(i,j)表示切割序号为i,j的切点处的小木棒的最优费用。用数组a存储切点的位置,则状态转移方程如下:
d(i,j)=min{d(i,k)+d(k,j)|i<k<j}+a[j]-a[i];
其中,a[j]-a[i]表示切割序号为i到j的小木棒的第一刀的费用。切完后,小木棒变为i~k,k~j两部分。如果设所有切点是1~n,左边界是0,右边界是n+1,那么本题答案是d(0,n+1)。本题的状态有O(N^2)个,每个状态的决策有O(N)个,总时间复杂度为O(N^3)。本题适合用递推写法来计算d(i,j),速度比记忆化写法更快,而且更方便。这里枚举变量是j-i,且要从小到大枚举。因为长区间的结果依赖短区间的结果。
3.代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;
#define INF 1000000
#define maxn 50+10
int L;
int n;
int ans;
int a[maxn];
int d[maxn][maxn];
int main()
{
//freopen("test.txt", "r", stdin);
while (scanf("%d", &L) == 1 && L)
{
memset(a, 0, sizeof(a));
memset(d, 1000000, sizeof(d));
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", a + i);
a[0] = 0;
a[n + 1] = L;
for (int i = 0; i < n + 1; i++)//计算长度为1的
d[i][i + 1] = 0;
for (int i = 0; i < n; i++)//长度为2的
d[i][i + 2] = a[i + 2] - a[i];
for (int len = 3; len <= n + 1; len++)//枚举长度
for (int i = 0; i <= n + 1 - len; i++)
{
int j = i + len;
for (int k = i + 1; k < j; k++)
{
int temp;
temp = d[i][k] + d[k][j] + a[j] - a[i];
d[i][j] = min(d[i][j], temp);
}
}
printf("The minimum cutting is %d.\n", d[0][n+1]);
}
return 0;
}