C. Road Optimization codeforces 1625C

https://codeforces.com/problemset/problem/1625/C

题目大意:在坐标0到l的数轴上,有n个限速点,每个限速点到下一个限速点之间每个单位长度的速度等于限速,现给出每一个点的坐标di和限速ai,坐标为0处必有一个限速点,现在可以删除不超过k个限速点,问从0到l的最短时间是多少

1<=n<=500;1<=l<=1e5;0<=k<=n-1;1<=ai<=1e4

思路:因为如果我们删除了一个点,那么它后面的距离等于它前一个限速点的限速,而如果再把前一个点删掉,那么这一段的速度又等于另一个点,所以删的每一个点都对后面的点有影响,无法从局部最优推到局部最优,那么只能用动态规划来做。

        用dp[i][j]表示前i个点中删除了j个点的最短时间,我们遍历i,遍历j,然后遍历i之前的每一个点jj,如果当前已删除的点的数量>=i之后删除的点的数量i-jj,也就是前jj个点删了0-k个点,那么从前jj个点转移过来的方程就是dp[i][j]=dp[jj][j-(i-jj-1)]+a[jj]*(d[i]-d[jj]),这样便可以枚举到所有可能情况,然后我们在i=n+1的时候维护一下答案的最小值即可

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
int a[505], b[505];
int dp[505][505];
int main()
{
	int n, l, k;
	cin >> n >> l >> k;
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &a[i]);
	}
	a[n+1] = l;//记录终点的坐标
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &b[i]);
	}
	for (int i = 0; i <= n+1; i++)
	{
		for (int j = 0; j <= n+1; j++)
		{
			dp[i][j] = 1e9;//要求最小值,所以初始化为极大值
		}
	}
	dp[1][0] = 0;
	int ans = 1e9;
	for (int i = 2; i <= n+1; i++)
	{//当前已选择了i个点,包括起点
		for (int j = 0; j<=k; j++)
		{//当前已删除的点的数量
			for (int jj = 1; jj < i; jj++)
			{//遍历已选择的点
				if (j >= i - jj - 1)//已删除的点的数量大于等于i后面删除的点的数量
					dp[i][j] = min(dp[i][j], dp[jj][j - (i - jj - 1)] + b[jj] * (a[i] - a[jj]));//从未删除的点处转移
			}
			if (i == n+1)
			{//维护最小值
				ans = min(ans, dp[i][j]);
			}
		}
	}	
	printf("%d\n", ans);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

timidcatt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值