acwing 3394. 最小花费
题目描述
某条线路上有 NN 个火车站,按顺序依次编号为 1∼N1∼N。
对于第 ii 号车站(i≥2i≥2),11 号车站与该车站之间的距离为 aiai。
显然,aiai 序列是递增的。
乘客在购票时,有三种车票可选:
- 当起点站和终点站之间的距离 SS 满足 0<S≤L10<S≤L1 时,票价为 C1C1 元。
- 当起点站和终点站之间的距离 SS 满足 L1<S≤L2L1<S≤L2 时,票价为 C2C2 元。
- 当起点站和终点站之间的距离 SS 满足 L2<S≤L3L2<S≤L3 时,票价为 C3C3 元。
注意,由于只出售上述三种车票,所以当起点站和终点站之间的距离 SS 大于 L3L3 时,只能选择从中途一些车站下车,重新买票的方式不断延续旅途直至到达终点站。
换句话说,这种情况下,乘客至少要买两张或更多车票才能到达终点站。
保证任意两个相邻车站之间的距离不超过 L3L3。
现在,某乘客要在 AA 号车站上车,并在 BB 号车站下车。
请你计算他所需要的最小花费是多少。
输入格式
第一行包含 66 个整数 L1,L2,L3,C1,C2,C3L1,L2,L3,C1,C2,C3。
第二行包含两个整数 A,BA,B。
第三行包含一个整数 NN。
接下来 N−1N−1 行,每行包含一个整数,依次表示 a2∼aNa2∼aN,保证这 N−1N−1 个数严格单调递增。
输出格式
输出一个整数,表示乘客的最小花费。
数据范围
1≤L1<L2<L3≤10001≤L1<L2<L3≤1000,
1≤C1<C2<C3≤10001≤C1<C2<C3≤1000,
1≤A<B≤N1≤A<B≤N,
1≤N≤10001≤N≤1000,
1≤ai≤1061≤ai≤106输入样例:
1 2 3 1 2 3 1 2 2 2
输出样例:
2
动态规划:区间dp / 一维dp
分析
我想到的是区间dp,但是只过了八个点
在牛客清华机试题上有相同的题目,我把代码交上去过了
在牛客评论区看到一维dp的写法,记录一下
代码
区间dp代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 1010;
const int INF = 0x3f3f3f3f;
int l1, l2, l3, c1, c2, c3;
int a, b;
int n;
int s[N];
LL f[N][N]; // f[i][j]表示从i到j的最小花费
// 要保证cost <= l3
int get_fee(int cost)
{
if (cost <= l1) return c1;
else if(cost <= l2) return c2;
else if(cost <= l3) return c3;
}
int main()
{
scanf("%d%d%d%d%d%d", &l1, &l2, &l3, &c1, &c2, &c3);
scanf("%d%d", &a, &b);
scanf("%d", &n);
s[1] = 0;
for(int i = 2; i <= n; i++)
scanf("%d", &s[i]);
int cost = s[b] - s[a];
if (cost <= l1) printf("%d\n", c1);
else if(cost <= l2) printf("%d\n", c2);
else if(cost <= l3) printf("%d\n", c3);
else //
{
// len = 1
for(int i = a + 1; i <= b; i++)
{
int cost = s[i] - s[i - 1]; // 一定小于l3
f[i-1][i] = get_fee(cost);
}
for(int len = 2; len <= b-a; len++)
{
for(int i = a; i + len <= b; i++)
{
int l = i, r = i + len;
int cost = s[r] - s[l];
if (cost <= l1) f[l][r] = c1;
else if(cost <= l2) f[l][r] = c2;
else if(cost <= l3) f[l][r] = c3;
else
{
f[l][r] = INF;
for(int k = l+1; k <= r-1; k++)
{
f[l][r] = min(f[l][r], f[l][k] + f[k][r]);
}
}
}
}
printf("%lld\n", f[a][b]);
}
return 0;
}
一维dp代码
#include <stdio.h>
#include <limits.h>
#define N 500
int dist[N], cost[N];//第i个站的总里程、最少花费
int l1, l2, l3, c1, c2, c3;
int Price(int L)//L距离的票多少钱
{
if(L<=l1) return c1;
else if(L<=l2) return c2;
else return c3;
}
int main()
{
int n, from, to;
while(scanf("%d%d%d%d%d%d",&l1,&l2,&l3,&c1,&c2,&c3)!=EOF)
{
dist[1]=0;//始发站里程为0
scanf("%d %d", &from, &to);
scanf("%d", &n);
for(int i=2; i<=n; i++) scanf("%d", &dist[i]);
cost[from]=0;//出发之前,没花一毛钱
for(int i=from+1; i<=to; i++)//前进!!!
{
cost[i]=INT_MAX;//先假设到i站需要花无数的钱
for(int j=from; j<i; j++)//到i站的票可能是从j站买的
{
int L=dist[i]-dist[j];//j站到i站的距离
if(L<=l3&&cost[j]+Price(L)<cost[i])
{//如果从j站买票能比以往的方案更省钱,那就从j买票
cost[i]=cost[j]+Price(L);
}
}
}
printf("%d\n", cost[to]);
}
return 0;
}
// https://www.nowcoder.com/practice/e6df3e3005e34e2598b9b565cfe797c9?tpId=60&tqId=29495&tPage=2&rp=2&ru=/ta/tsing-kaoyan
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!