【Uva 1336】Fixing the Great Wall

Link:

Description

给你长城上的n个修补点,然后你的位置为x;
你需要依次去这n个点,然后把它们全部修好.
但是修的前后顺序不一样的话,花费不一样.
如果立即把第i个点修好的话,需要c[i]点花费;
每多t秒钟,就要多花费t*d[i]点花费.
你一开始的位置在x,然后你的移动速度为v;
修完所有的点的最小花费.

Solution

区间动态规划
在任意时刻,你当前的位置,和你之前走的位置肯定是在连续的一段区间上的,因为你不可能跳过一个点不修,而去修它旁边的一个点.因为修的时候不用花费时间,是立刻就修好的!
这样;
设f[i][j][p]表示i..j这段区间全都走完了,现在在i..j这段区间的p端的最小花费,p=0表示左边,否则右边;
把那个初始位置X放到n+1的位置;
然后n++
再把1..n按照x升序排序;
从X的位置开始进行DP;
X的位置是第i个;
则从状态f[i][i][0]开始进行DP;
因为这个状态不能知道走了多长的时间;
所以可以用颜色长度这道题的思路,在进行一步扩展的时候;
比如从i到了i-1;
则t = (x[i]-x[i-1])/v;
把1..i-1和i+1..n这些点的d[i]值的和乘上t加到答案里面去;
(因为那些点的d值肯定是要乘上这个t值的);
下次遇到那些点的时候,就只加上c值就可以了;
这个f值要用double存,不能用整形;
最后输出的时候
用floor输出.

NumberOf WA

3

Reviw

这类题,因为修理的时间不计,所以最后肯定是形成一段段的区间.

Code

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int N = 1000;
const ll INF = 1e9+10;

struct abc{
    double x,c,d;
};

int n;
double v,X;
double f[N+10][N+10][2],sum[N+10];
abc a[N+100];

int cmp(abc a,abc b){
    return a.x < b.x;
}

double get_sum(int x,int y){
    if (x>y) return 0;
    return sum[y]-sum[x-1];
}

double dfs(int l,int r,int p){
    if (f[l][r][p]>0){
        return f[l][r][p];
    }
    if (l==1 && r==n) return 0;
    double t1,t2,temp1 = -1,temp2 = -1;
    if (p==0){
        if (l-1>=1){
            t1 = (a[l].x-a[l-1].x)/v;
            temp1 = dfs(l-1,r,0) + a[l-1].c + get_sum(1,l-1)*t1
                + get_sum(r+1,n)*t1;
        }
        if (r+1<=n){
            t2 = (a[r+1].x-a[l].x)/v;
            temp2 = dfs(l,r+1,1) + a[r+1].c + get_sum(1,l-1)*t2
                + get_sum(r+1,n)*t2;
        }
    }else{//p==1
        if (l-1>=1){
            t1 = (a[r].x-a[l-1].x)/v;
            temp1 = dfs(l-1,r,0) + a[l-1].c + get_sum(1,l-1)*t1
                + get_sum(r+1,n)*t1;
        }
        if (r+1<=n){
            t2 = (a[r+1].x-a[r].x)/v;
            temp2 = dfs(l,r+1,1) + a[r+1].c + get_sum(1,l-1)*t2
                + get_sum(r+1,n)*t2;
        }
    }
    double &key = f[l][r][p];
    if (temp1<0) return key = temp2;
    if (temp2<0) return key = temp1;
    return key = min(temp1,temp2);
}

int main(){
    //freopen("F:\rush.txt","r",stdin);
    while (~scanf("%d%lf%lf",&n,&v,&X)){
        if (n==0) break;
        for (int i = 1;i <= n;i++)
            scanf("%lf%lf%lf",&a[i].x,&a[i].c,&a[i].d);
        a[n+1].x=X,a[n+1].c = 0,a[n+1].d = 0;
        n++;
        sort(a+1,a+1+n,cmp);
        sum[0] = 0;
        for (int i = 1;i <= n;i++)
            sum[i] = sum[i-1] + a[i].d;

        for (int i = 1;i <= n;i++)
            for (int j = 1;j <= n;j++)
                f[i][j][0] = f[i][j][1] = -1;

        for (int i = 1;i <= n;i++)
            if (a[i].d==0){
                printf("%.0f
",floor(dfs(i,i,0)));
                break;
            }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/AWCXV/p/7626180.html