题目
设有一个长度为L的钢条,在钢条上标有n个位置点(p1,p2,…,pn)。现在需要按钢条上标注的位置将钢条切割为n+1段,假定每次切割所需要的代价与所切割的钢条长度成正比。请编写一个算法,能够确定一个切割方案,使切割的总代价最小。
题解
* DP
*/
#include<bits/stdc++.h>
using namespace std;
int min (int a, int b) {
return a < b ? a : b;;
}
/**
* j-i=1 ==> a[i][j]=0;
* j-i=2 ==> a[i][j]=p[j]-p[i];
* 3<=j-i ==> a[i][j]=min{p[j]-p[i]+a[i][k]+a[k][j]}; i+1<=k<=j-1
*/
int solve (int begin, int end, int *p, int **dp) {
if (end - begin == 1)
return 0;
else if (end - begin == 2)
return p[end] - p[begin];
else {
int least = dp[begin][begin + 1] + dp[begin + 1][end] + p[end] - p[begin];
for (int i = 2; i < end - begin; i++) {
least = min (least, dp[begin][begin + i] + dp[begin + i][end] + p[end] - p[begin]);
}
return least;
}
}
int main() {
cout << "Please input the length of steal bar:";
int L, n;
cin >> L;
cout << "Please input n:";
cin >> n;
int *p;
p = new int[n + 2];
p[0] = 0;
cout << "Please input the cut points:";
for (int i = 1; i < n + 1; i++) {
cin >> p[i];
}
sort (p + 1, p + n + 1);
p[n + 1] = L;
int **dp = new int*[n + 2];
for (int i = 0; i < n + 2; i++) {
dp[i] = new int[n + 2];
}
for (int i = 1; i < n + 2; i++) {
for (int j = 0; j < n + 2 - i; j++) {
dp[j][i + j] = solve (j, i + j, p, dp);
}
}
cout << solve (0, n + 1, p, dp);
return 0;
}