Fixing the Great Wall UVA

一到神奇的题目

dp[i][j] 表示i到j已修好,再加一维,0表示在左边1表示在右边

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

const double inf = 1e30;

const int maxn = 1e3+10;

int n,vis[maxn][maxn][2],kase=0;

double v,x,d[maxn][maxn][2],sumd[maxn];

struct node {
    double x,c,d;
    bool operator <(const node& a) const {
        return x<a.x;
    }
}gw[maxn];

double cost(double x1,double x2,int i,int j) {
    //if(i>j) return inf;
    double a=0;
    if(i>=0&&j>=0) a=sumd[j]-sumd[i-1];
    return (sumd[n]-a)/v*fabs(x1-x2);
}

double dp(int i,int j,int p) {
    //if(i>j) return inf;
    if(i==1&&j==n) return 0;
    double& ans = d[i][j][p];
    if(vis[i][j][p]==kase) return ans;
    vis[i][j][p]=kase;
    ans=inf;
    double x=p==0?gw[i].x:gw[j].x;
    if(i>1) ans=min(ans,dp(i-1,j,0)+cost(x,gw[i-1].x,i,j));
    if(j<n) ans=min(ans,dp(i,j+1,1)+cost(x,gw[j+1].x,i,j));
    return ans;
}

int main() {
    //freopen("in.txt","r",stdin);
    while(scanf("%d%lf%lf",&n,&v,&x)==3&&n) {
        ++kase;
        double sumc=0;
        for(int i=1;i<=n;i++) {
            scanf("%lf%lf%lf",&gw[i].x,&gw[i].c,&gw[i].d);
            sumc+=gw[i].c;
        }
        sort(gw+1,gw+1+n);
        sumd[0]=0;
        for(int i=1;i<=n;i++) {
            sumd[i]=sumd[i-1]+gw[i].d;
        }
        gw[0].x=-inf;gw[n+1].x=inf;//设边界,好判断
        double ans=inf;
        for(int i=1;i<=n+1;i++) {//找起点
            if(x>gw[i-1].x&&x<gw[i].x) {
                if(i>1) ans=min(ans,dp(i-1,i-1,0)+cost(x,gw[i-1].x,-1,-1));//左移
                if(i<=n) ans=min(ans,dp(i,i,0)+cost(x,gw[i].x,-1,-1));//右移
            }
        }
        printf("%.0lf
",floor(ans+sumc));
    }
    return 0;
} 
View Code

题目描述

为了简化这个问题,我们把长城看成是一条直线,每个需要修补的点都被用它离起点的距离(一个整数)标记了。GWARR被放在长城的一个随机位置上,并且可以以恒定的速度双向移动。每个点距离起点的距离,现在立即修复的花费,以及每过单位时间修复花费的增长量都已知。GWARR的工作效率极高,以至于它可以立即修复好经过的需要修复的地方。

输入输出格式

输入格式

输入包含多组测试数据。每组测试数据的格式如下: 第一行包含333个整数N,V,XN, V, XN,V,X,分别表示点的数量,GWARR的移动速度,GWARR的出发点位置。
接下来nnn行,每行333个整数x,c,Δx,c,Deltax,c,Δ,表示这个点的位置,现在立即修复的花费,以及每过单位时间修复花费的增长量。保证没有两个点的位置相同。
输入以一行N=V=X=0N=V=X=0N=V=X=0作为结束标记。

输出格式

NNN行,每行一个整数,表示每组数据的最小总花费(向下取整),保证输出结果不超过10910^9109。

样例输入输出

样例输入#1:

3 1 1000
1010 0 100
998 0 300
996 0 3
3 1 1000
1010 0 100
998 0 3
996 0 3
0 0 0 

样例输出#1:

2084
1138

样例输入输出解释:

对于第一种情况,我们选择先修复距离998998998处,花费600600600,然后是101010101010处,花费140014001400,然后是996996996处,花费848484。合计208420842084。

数据范围与提示:

数据范围:

对于100%100 \%100%数据有: 1≤N≤1000,1≤V≤100,1≤X≤500,0001 leq N leq 1000, 1 leq V leq 100,1 leq X leq 500,0001N1000,1V100,1X500,000;
1≤x≤500,000,1≤c≤50,000,1≤Δ≤50,0001 leq x leq 500,000, 1 leq c leq 50,000, 1 leq Delta leq 50,0001x500,000,1c50,000,1Δ50,000。

提示:

输出格式中的“向下取整”是针对输出的答案而言的,在计算过程中应该使用double,而不是int

由 @Sparky_14145 提供翻译

原文地址:https://www.cnblogs.com/plysc/p/10881367.html