uva1336 Fixing the Great Wall

Posted w19567

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uva1336 Fixing the Great Wall相关的知识,希望对你有一定的参考价值。

https://vjudge.net/problem/UVA-1336

 

显然最佳的移动方式一定是向左走一段,向右走一段,再向左走一段,再向右走一段......(或者反过来)

无论如何中间的会最先被修理好,所以考虑区间dp

$f_i,j,0/1$表示修理好了$i\rightarrow j$时,所用的最小费用(注意费用提前计算)

预处理处$cl_i,j(i\leq j)$表示从$i$出发修理到$j$的费用

$cr_i,j(i\geq j)$从$i$出发修理到$j$的费用

然后就是转移了(其实还是很好想的),由于决策集合不会变小,所以可以用一个标记记录一下最小值,$O(1)$转移

 

#include<bits/stdc++.h>
using namespace std;
const int N=1005;
const double inf=1000000000.0,eps=0.000001;
int n,v,x,st;
struct nodeint c,d,x; sec[N];
double f[N][N][2],cl[N][N],cr[N][N];
double sum[N],min0[N],min1[N],bs;
void clear()

    st=0,bs=0;
    for(int i=0;i<N;++i)
    
        sum[i]=0,cl[i][i]=0;
        min0[i]=min1[i]=inf;
    

double tme(int a,int b) return (double)abs(sec[a].x-sec[b].x)/(double)v;
bool cmp(node a,node b) return a.x<b.x;
int main()

    while (scanf("%d%d%d", &n, &v, &x)==3 && n)
    
        if(!n && !v && !x) return 0;
        clear();
        for(int i=1;i<=n;++i)
            scanf("%d%d%d",&sec[i].x,&sec[i].c,&sec[i].d);
        sort(sec+1,sec+n+1,cmp);
        sec[n+1].x=x+1;
        for(int i=1;i<=n+1;++i)
            if(sec[i].x>x) st=i-1;break;
        for(int i=1;i<=n;++i)
            for(int j=i+1;j<=n;++j)
                cl[i][j]=cl[i][j-1]+tme(i,j)*sec[j].d;
        for(int i=1;i<=n;++i)
            for(int j=i-1;j>=1;--j)
                cr[i][j]=cr[i][j+1]+tme(i,j)*sec[j].d;
        for(int i=1;i<=n;++i) sum[i]=sum[i-1]+sec[i].d,bs+=sec[i].c;
        if(!st) 
            printf("%.0lf\n",floor(bs+cl[1][n]+1.0*(sec[1].x-x)/(1.0*v)*sum[n]+eps));
            continue;
        
        if(st==n) 
            printf("%.0lf\n",floor(bs+cr[n][1]+1.0*(x-sec[n].x)/(1.0*v)*sum[n]+eps));
            continue;
        
        f[st][st][0]=f[st][st][1]=1.0*(x-sec[st].x)/(1.0*v)*sum[n];
        f[st+1][st+1][0]=f[st+1][st+1][1]=1.0*(sec[st+1].x-x)/(1.0*v)*sum[n];
        min0[st]=min1[st]=f[st][st][0];
        min0[st+1]=min1[st+1]=f[st+1][st+1][0];
        for(int i=2;i<=n;++i)
            for(int j=max(1,st-i+1);j<=st+1 && i+j-1<=n;++j)
            
                int l=j,r=j+i-1;
                double pre=sum[n]-sum[r]+sum[l-1];
                f[l][r][0]=min0[r]+cr[r][l]+tme(r,l)*pre;
                f[l][r][1]=min1[l]+cl[l][r]+tme(r,l)*pre;
                min0[r]=min(min0[r],f[l][r][1]-cr[r][l]);
                min1[l]=min(min1[l],f[l][r][0]-cl[l][r]);
                //cout<<l<<" "<<r<<" "<<f[l][r][0]<<" "<<f[l][r][1]<<endl;
            
        printf("%.0lf\n",floor(min(f[1][n][0],f[1][n][1])+bs+eps));
    
    return 0;

 

以上是关于uva1336 Fixing the Great Wall的主要内容,如果未能解决你的问题,请参考以下文章

UVa 1336 Fixing the Great Wall (区间DP)

UVA10256 The Great Divide(凸包相交)

UVA1045 The Great Wall Game

UVA 10256 The Great Divide (判断凸包相交)

UVA 10256 The Great Divide (凸包,多边形的位置关系)

UVA10256 The Great Divide