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; }
时间: 2024-11-03 21:59:00