卡车更新问题

69 篇文章 0 订阅

卡车更新问题


Description

某人购置了一辆新卡车, 从事个体运输业务. 给定以下各有关数据: R[t],t=01,2,...,k , 表示已使用过 t 年的卡车, 再工作一年所得的运费, 它随 t 的增加而减少, k (k20) 年后卡车已无使用价值.
U[t]t=01,...,k , 表示已使用过 t 年的卡车, 再工作一年所需的维修费, 它随 t 的增加而增加.
C[t]t=01,2,...,k , 表示已使用过 t 年的旧卡车, 卖掉旧车, 买进新车, 所需的净费用, 它随 t 的增加而增加.
以上各数据均为实型, 单位为”万元”.
设某卡车已使用过 t 年,
① 如果继续使用, 则第 t+1 年回收额为 R[t]U[t] ,
② 如果卖掉旧车,买进新车, 则第 t+1 年回收额为 R[0]U[0]C[t] .
该运输户从某年初购车日起,计划工作 N(N<=20) 年, N 年后不论车的状态如何,不再工作.
为使这 N 年的总回收额最大, 应在哪些年更新旧车? 假定在这N年内, 运输户每年只用一辆车, 而且以上各种费用均不改变.


Input

1 行: N (运输户工作年限)
2 行: k (卡车最大使用年限, k≤20 )
3 行: R[0] R[1] ... R[k]
4 行: U[0] U[1] ... U[k]
5 行: C[0] C[1] ... C[k]


Output

1 行: W ( N 年总回收额)
2 N+1 行: 每行输出 3 个数据:
年序号 ( 从 1 N 按升序输出);
否更新 ( 当年如果更新,输出 1, 否则输出 0 );
当年回收额 ( N 年回收总额应等于 W ).


Sample Input

4
5
8 7 6 5 4 2
0.5 1 2 3 4 5
0 2 3 5 8 10


Sample Output

24.5
1 0 7.5
2 1 5.5
3 1 5.5
4 0 6.0


Solution

fi,j i 年使用的卡车年限为 j 的最大回收额。
j=1 表示它去年更新了,则

fi,j=Max{fi1,k+r[0]u[0]c[k]}

否则
fi,j=fi1,j1+r[j1]u[j1]


Code

#include <iostream>
#include <cstdio>
#include <cfloat>

#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))

using namespace std;

int n,k;

double r[30],u[30],c[30],f[100000][30];
int g[100000][30];
double ans=DBL_MIN;

void work(int year,int x){
    if(year==1)return;
    work(year-1,g[year][x]);
    if(x==1)printf("%d %d %.1lf\n",year,1,f[n][x]-f[n-1][g[year][x]]);
    else printf("%d %d %.1lf\n",year,0,f[n][x]-f[n-1][g[year][x]]);
}

int main(){

    freopen("truck.in","r",stdin);
    freopen("truck.out","w",stdout);

    memset(f,0xc2,sizeof f);
    double oo=f[0][0];

    scanf("%d%d",&n,&k);
    for(int i=0;i<=k;i++)scanf("%lf",&r[i]);
    for(int i=0;i<=k;i++)scanf("%lf",&u[i]);
    for(int i=0;i<=k;i++)scanf("%lf",&c[i]);

    f[1][1]=r[0]-u[0];
    for(int i=2;i<=n;i++){
        for(int j=1;j<=k;j++){
            if(j==1){
                for(int l=1;l<=k;l++)
                    if(f[i-1][l]!=oo){
                        if(f[i-1][l]+r[0]-u[0]-c[l]>f[i][j]){
                            f[i][j]=f[i-1][l]+r[0]-u[0]-c[l];
                            g[i][j]=l;
                        }
                    }
            }
            else{
                if(f[i-1][j-1]!=oo){
                    f[i][j]=f[i-1][j-1]+r[j-1]-u[j-1];
                    g[i][j]=j-1;
                }
            }
        }
    }
    int ttt;
    for(int i=0;i<=k;i++){
        if(f[n][i]>ans){
            ans=f[n][i];
            ttt=i;
        }
    }
    printf("%.1lf\n",ans);
    printf("%d %d %.1lf\n",1,0,r[0]-u[0]);
    work(n,ttt);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值