Fixing the Great Wall UVA - 1336(区间dp+前缀和)

题目连接; 点击打开链接

题目大意:给出n个坏掉的东西的坐标,和 初始花费,以及增长速度,给出机器人的速度和初始坐标,问最少花费能修好全部东西。

题目思路:很容易知道机器人修理好的东西一定是一个连续的区间,并且每一次都会有不同的决策们很容易知道是dp,我们定义状态dp[i][j]为修理好了i到j需要的最少花费,

接下来很容易发现还需要知道机器人在区间的哪一端,所以我们定义状态dp[i][j][2],为修好了i到j机器人在最左端和最右端最小花费,然后从机器人起点往外扩展就行了,

这里有个技巧就是吧起点也当作一个坏掉的东西处理,接下来还有一个烦人的就是怎么往外扩展,用记搜当然可以,不过还是递推比较方便,详情看代码

ac代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstring>
#include<iostream>
#include<sstream>
#include<cmath>
#include<vector>
#define LL long long
#define INF 0x3f3f3f3f
#define eps 1e-6
#include<deque>
using namespace std;
const int maxn = 1e9+5;
double dp[1005][1005][2];
int sum[1005];
int sum2[1005];
struct node
{
    int pos;
    int cost;
    int ic;
}E[1005];
int n,v,x;
int cmp(node a,node b)
{
    return a.pos<b.pos;
}
int main()
{
    while(~scanf("%d%d%d",&n,&v,&x)){
        if(n+v+x==0)
        return 0;
        for(int i = 0;i<=n+1;i++){
            for(int j = 0;j<=n+1;j++){
                dp[i][j][0] = (double)maxn;
                dp[i][j][1] = (double)maxn;
            }
        }
        E[n+1].pos  = x;
        E[n+1].cost = E[n+1].ic = 0;
        for(int i = 1;i<=n;i++){
            scanf("%d%d%d",&E[i].pos,&E[i].cost,&E[i].ic);
        }
        sort(E+1,E+n+2,cmp);
        for(int i = 1;i<=n+1;i++){
            sum[i] = sum[i-1] + E[i].ic;
        }
        for(int i = 1;i<=n+1;i++){
            sum2[i] = sum2[i-1]+E[i].cost;
        }
        int s;
        for(int i = 1;i<=n+1;i++){
            if(E[i].pos == x){
            s = i;
            break;
            }
        }
        dp[s][s][0] = dp[s][s][1] = 0;
        for(int i = s;i>=1;i--){
            for(int j = s;j<=n+1;j++){
                if(i>1){
                double t = abs(E[j].pos-E[i-1].pos)*1.0/v;
                dp[i-1][j][0] = min(dp[i-1][j][0],dp[i][j][1]+E[i-1].cost+t*(sum[i-1]+sum[n+1]-sum[j]));
                t = abs(E[i].pos-E[i-1].pos)*1.0/v;
                dp[i-1][j][0]  = min(dp[i-1][j][0],dp[i][j][0]+E[i-1].cost+t*(sum[i-1]+sum[n+1]-sum[j]));
                }
                if(j<n+1){
                    double t = abs(E[j+1].pos-E[j].pos)*1.0/v;
                dp[i][j+1][1] = min(dp[i][j+1][1],dp[i][j][1]+E[j+1].cost+t*(sum[i-1]+sum[n+1]-sum[j]));
                t = abs(E[j+1].pos-E[i].pos)*1.0/v;
                dp[i][j+1][1]  = min(dp[i][j+1][1],dp[i][j][0]+E[j+1].cost+t*(sum[i-1]+sum[n+1]-sum[j]));
                }
               // cout<<dp[i][j][0]<<' '<<i<<' '<<j<<endl;
                //cout<<dp[i][j][1]<<' '<<i<<' '<<j<<endl;
            }
        }
        printf("%d\n",(int)min(dp[1][n+1][0],dp[1][n+1][1]));
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值