题目:
给出木棍长度和固定的切点,由于切割顺序不同,费用会有所不同,收费规则:每一刀的费用为当前被切段长度,总费用为所有费用之和,求最小费用。如:长度10,切点坐标2,5,那么cost_min = 10 + 5 = 15(格式略)
题目详情参考链接 https://vjudge.net/problem/UVA-10003
博主有话说:
动态规划刚接触,对dp真是不太懂,边摸索边借鉴才整出的代码,慢慢来相信可以克服!!!(ง •_•)ง
思路:
总体思路:遍历所有切法,取出最小值(不超时难喽)
思路解析:我们倒着想,就差最后一刀,只有一种结果;若最后两刀,就两种结果;以此类推,直到第一刀,仅有n种结果,取最小即可。类似汉诺塔的问题,由内向外层层包装,求解外层只需向内层层解包。
那么由于切每一刀的方式不唯一,我们可以用循环实现,得到每一刀的最小费用,刀刀相加即最小总费用啦。
需要注意在深入内层解包时,有些包已经被解过啦,而且已经被记录了下来,直接拿来用避免重复解包 细节见代码
核心代码:
const int INF = 0x3f3f3f3f;
int len, n;
int cut[55]; //记录切点
int cost[55][55]; //记录起点cut[i]终点cut[j]的木棍 其切割de最小费用
int dp (int i, int j) {
if(i+1 >= j) return 0; //无处可切
if(cost[i][j] < INF) return cost[i][j]; //已解过
for(int k = i + 1; k < j; k++) //找到当前这一刀的最小费用
cost[i][j] = min(cost[i][j], dp(i, k) + dp(k, j) + (cut[j]-cut[i]));
return cost[i][j];
}
int main() {//int T; cin >> T; getchar()
while(scanf("%d", &len) && len && scanf("%d", &n)) {
cut[0] = 0; cut[n+1] = len; //这一步很重要 需要加两个端点
for(int i = 1; i <= n; i++)
scanf("%d", &cut[i]);
memset(cost, INF, sizeof(cost));
printf("The minimum cutting is %d.\n", dp(0, n+1));
}
return 0;
}
其实在家真的无聊,你们说呢?