UVA - 1336 Fixing the Great Wall

问题

机器人修补长城,给三个整数,n代表缺口(缺口看作点),v(机器人行动速度),x(机器人现在所在位置),x不和任何缺损点重合,对于n个点,每个点有3个整数,x代表缺损点位置,c代表修补代价,delta代表随时间增加的代价,总代价是c+delta*t

输入

三个整数,n,v,x,后面n组点的参数,x,c,delta,最小花费不大于 1 e 9 1e^9

输出

修补花费,截断输出整数

思路

修复的点肯定是相连的,因为修复不花费时间,如果是中间有空的点没修复肯定不是最优解,状态是dp[i][j][k],[i,j]代表修复了的区域是【i-j】(点的编号按照x的从小到大排序),k大小为2,k=0代表机器人停在最左端点i处,k=1代表停在最右端

注意点

如何按照时间累计花费? 对于每个点来说,它随时间增加的花费是所有未修补点这段时间增加的花费的和(例如机器人到一个点时间乘以所有未修补点的delta之和,也就是机器人修补第一个点时的花费为point[1]。c+t*(sum(delta))),这样,每次到下一个点,都想当于从0开始计时

状态转移方程(填表法):
下一个修补点有两种可能,一种是修补左边的点,一种是修补右边的
修补左边的点:
f ( i , j , 0 ) = m i n ( f ( i + 1 , j , 0 ) + c o s t 1 , f ( i + 1 , j , 1 ) + c o s t 2 ) f(i,j,0)=min(f(i+1,j,0)+cost1,f(i+1,j,1)+cost2) 修左边的i-1点有两种情况,一种是机器人在i处向左移动,移动和修补共cost1,一种是机器人在j点向左移动,移动和修补共cost2
修补右边的点:
f ( i , j , 1 ) = m i n ( f ( i , j 1 , 0 ) + c o s t 1 , f ( i , j 1 , 1 ) + c o s t 2 ) f(i,j,1)=min(f(i,j-1,0)+cost1,f(i,j-1,1)+cost2) 修补右边同理

bug: 一开始忘了在cost中加入points[k].c

#include<iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=1005,Inf=1500000000;
struct Point{
    int x,c,delta;
    Point(int x=0,int c=0,int delta=0):x(x),c(c),delta(delta) {}
    bool operator < (const Point &rhs) const {
        return x<rhs.x;
    }
};
Point points[maxn];
//dp[i][j][k]  [i,j]代表经历过了[i,j]这些点,k=0代表机器人在i,k=1代表机器人在j
int n,v,x,xi,ci,deltai,delta[2][maxn];
double dp[maxn][maxn][2];
//update state
void update(int i,int j,int k,int i2,int j2,int k2){
    if(dp[i2][j2][k2]>1e9) return;
    double diff=0;
    if(!k2 && !k) diff=fabs((points[i2].x-points[i].x)*1.0/v);
    else if(!k2 && k) diff=fabs((points[i2].x-points[j].x)*1.0/v);
    else if(k2 && !k) diff=fabs((points[j2].x-points[i].x)*1.0/v);
    else if(k2 && k) diff=fabs((points[j2].x-points[j].x)*1.0/v);
    dp[i][j][k]=min(dp[i][j][k],dp[i2][j2][k2]+points[(k==0)?i:j].c+diff*(delta[0][i2-1]+delta[1][j2+1]));
}

int main(void){
    while(cin>>n>>v>>x && n){
        for(int i=1;i<=n;++i){
            scanf("%d%d%d",&points[i].x,&points[i].c,&points[i].delta);
        }
        sort(points+1,points+n+1);
        memset(delta,0,sizeof(delta));
        for(int i=1;i<=n;++i) dp[i][i][0]=dp[i][i][1]=Inf;
        for(int i=1;i<=n;++i) delta[0][i]=delta[0][i-1]+points[i].delta;
        for(int i=n;i>=1;--i) delta[1][i]=delta[1][i+1]+points[i].delta;

        int k=int(lower_bound(points+1,points+1+n,Point(x,0,0))-points);
        if(k>=1 && k<=n) dp[k][k][0]=dp[k][k][1]=points[k].c+(points[k].x-x)*1.0/v*(delta[0][k]+delta[1][k+1]);
        if(k-1>=1 && k-1<=n)
            dp[k-1][k-1][0]=dp[k-1][k-1][1]=points[k-1].c+(x-points[k-1].x)*1.0/v*(delta[0][k-1]+delta[1][k]);
        for(int d=1;d<n;++d){
            for(int i=1;i<=n;++i){
                if(i+d>n) break;
                int j=i+d;
                dp[i][j][0]=dp[i][j][1]=Inf;
                update(i,j,0,i+1,j,0);
                update(i,j,0,i+1,j,1);
                update(i,j,1,i,j-1,0);
                update(i,j,1,i,j-1,1);
            }
        }
        int ans=int(min(dp[1][n][0],dp[1][n][1]));
        printf("%d\n",ans);
    }
}
发布了15 篇原创文章 · 获赞 0 · 访问量 176

猜你喜欢

转载自blog.csdn.net/zpf1998/article/details/103913199