[区间DP] UVa10003 切木棍 (巧妙的边界处理)(离散化)

题目

这里写图片描述

思路

1.状态定义:d(i,j),切割位于切割点i和j之间的木棍需要的最小费用。
2.初状态:d(i,i+1) = 0,A[0] = 0, A[n+1] = L
3.答案:d(0,n+1)
4.状态转移方程:

d ( i , j ) = m i n { d ( i , k ) + d ( k , j ) + A [ j ] A [ i ] }

5.复杂度: O ( n 3 )


1.注意本题的边界处理,很巧妙
2.本题其实根据切割点来进行DP,特别是A[j]-A[i]这个操作,很厉害的离散化。数据量从1000降到了50。

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
#define _rep(i,a,b) for(int i = (a); i<=(b); i++)
using namespace std;

const int INF = 100000;
const int maxn = 50 + 5;
int n, L, A[maxn], d[maxn][maxn];

int main() {
    while (scanf("%d", &L) == 1 && L) {
        scanf("%d", &n);
        _rep(i, 1, n) scanf("%d", &A[i]);

        A[0] = 0;
        A[n + 1] = L;
        // _rep(i,0,n) d[i][i+1] = 0;
        int j;
        _rep(l,2,n+1)
            _rep(i, 0, n) {
                j = i + l;
                if (j > n + 1) continue;
                d[i][j] = INF;
                _rep(k, i + 1, j - 1)
                    d[i][j] = min(d[i][j], d[i][k] + d[k][j] + A[j] - A[i]);
            }
        printf("The minimum cutting is %d.\n", d[0][n + 1]);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/icecab/article/details/80940484