一开始我是这么做的
int main()
{
freopen("sb.txt", "r", stdin);
int t;
while (scanf("%d",&t)&&t)
{
//t代表木棒的长度
// memset(dp,)
//fill(dp, dp + MAX * MAX, 0x3f3f3f3f);
memset(dp, 0x3f3f3f3f, sizeof(dp));
int sum;
scanf("%d", &sum);
for (int i = 0; i < sum; i++)
{
int n;
cin >> n;
record[i + 1] = n;
}
record[0] = 0;
record[sum + 1] = t;
//dp[0][0] = 0;
for (int i = 0; i <= sum; i++)
{
dp[record[i]][record[i]] = 0;
}
for (int i = 1; i <=sum; i++)
{
dp[0][record[i]] = record[i];
}
for (int i = 1; i <=sum; i++)
{
dp[record[i]][t+1] = t - record[i];
}
for (int i = 0; i <= t; i++)
{
for (int j = i + 1; j <= t+1; j++)
{
for (int k = i+1; k <j; k++)
{
// cout << dp[i][k] + dp[k][j] + record[j] - record[i] << endl;
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + record[j] - record[i]);
}
}
}
cout << dp[0][t+1] << endl;
}
return 0;
}
如果用循环的方法,计算这样的状态转移肯定会出错
for (int i = 0; i <= t; i++)
{
for (int j = i + 1; j <= t+1; j++)
{
for (int k = i+1; k <j; k++)
{
// cout << dp[i][k] + dp[k][j] + record[j] - record[i] << endl;
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + record[j] - record[i]);
}
}
}
因为很明显当
d
p
[
i
]
[
k
]
dp[i][k]
dp[i][k]被计算出来的时候,
d
p
[
k
]
[
j
]
dp[k][j]
dp[k][j]还没有被计算出来。
所以如果状态转移方程不变的话,这种循环的方式是没有办法计算出正确答案的。
所以我们只能用递归搜索的方式来求解这个问题
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
#define MAX 1030
#define INF 0x3f3f3f3f
int dp[MAX][MAX];
int record[55];
int get_DP(int l, int r)
{
if (l == r - 1)return dp[l][r] = 0;
if (dp[l][r]!=INF)return dp[l][r];
//dp[l][r] = 0x3f3f3f3f;
for (int i = l + 1; i < r; i++)
{
dp[l][r] = min(dp[l][r], record[r] - record[l] + get_DP(l,i)+get_DP(i,r));
}
return dp[l][r];
}
int main()
{
freopen("sb.txt", "r", stdin);
int t;
while (scanf("%d",&t)&&t)
{
//t代表木棒的长度
// memset(dp,)
//fill(dp, dp + MAX * MAX, 0x3f3f3f3f);
memset(dp, 0x3f3f3f3f, sizeof(dp));
int sum;
scanf("%d", &sum);
for (int i = 0; i < sum; i++)
{
int n;
cin >> n;
record[i + 1] = n;
}
record[0] = 0;
record[sum + 1] = t;
//dp[0][0] = 0;
get_DP(0, sum + 1);
//cout << dp[0][sum+1] << endl;
printf("The minimum cutting is %d.\n", dp[0][sum + 1]);
}
return 0;
}
- d p [ l ] [ r ] dp[l][r] dp[l][r]代表在切割点i和切割点j切割的最小cost
- 如果 l = = r − 1 l==r-1 l==r−1则 d p [ l ] [ r ] = = 0 dp[l][r]==0 dp[l][r]==0因为这是一段肯定是完整的,是没有办法切割的。
- 一定要注意这里的边界条件 r e c o r d [ 0 ] = 0 ; r e c o r d [ s u m + 1 ] = t ; record[0] = 0; record[sum + 1] = t; record[0]=0;record[sum+1]=t;