Cutting Sticks UVA - 10003(dp不太懂ฅʕ•̫͡•ʔฅ慢慢来吧)

题目:

给出木棍长度和固定的切点,由于切割顺序不同,费用会有所不同,收费规则:每一刀的费用为当前被切段长度,总费用为所有费用之和,求最小费用。如:长度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;
}

其实在家真的无聊,你们说呢?

你可能感兴趣的:(DP(背包)题集(更))