CF1625C Road Optimization

CF1625C Road Optimization

洛咕传送门

  • 思路:

先看题目范围,\(n \leq 500\),而且题目中时间限制为 \(3\) s,预估时间复杂度上限 \(O(N^3)\)

尝试建分层图,发现边的长度随选择而变化,无法确定,故放弃。

考虑此类题目的经典做法:DP。

然而按照常规思路设 \(dp(i,j)\) 为前 \(i\) 个路标中删去 \(j\) 个,会发现无法确定状态,状态转移方程很难列出。
(upd:看了下官方题解,其实这样也是可行的,不过较为麻烦)

尝试反向思考:设 \(dp(i,j)\) 为前 \(i\) 个路标保留 \(j\) 个的最小路程,发现不难列出状态转移方程:

\[dp(i,j) = \min\limits_{1\le j\le i,1 \le q \lt i}\{dp[q][j-1]+\text{dist}(q,i)\} \]

其中 \(\text{dist}(q , i)\) 表示路标 \(q\)\(i\) 间,限速为 \(limit_q\) 时的路程。

初始状态:\(dp(1,1)=0\) 目标状态:\(_{n-k\le i \le n}\min\{dp(n,i)\}\)

code:

QAQ
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
using namespace std;
const int maxn = 505;
int dp[maxn][maxn],n,l,k,a[maxn],d[maxn];
void work() {
	scanf("%d%d%d",&n,&l,&k);
	for(int i = 1;i <= n;++ i)scanf("%d",&d[i]);
	for(int i = 1;i <= n;++ i)scanf("%d",&a[i]);
	d[++ n] = l;
	memset(dp , 0x3f , sizeof(dp));
	dp[1][1] = 0;
	for(int i = 2;i <= n;++ i) {
		for(int j = 1;j <= i;++ j) {
			for(int q = 1;q < i;++ q) {
				dp[i][j] = min(dp[i][j] , dp[q][j - 1] + a[q] * (d[i] - d[q]));
			}
		}
	}
	int sum = 0x3f3f3f3f;
	for(int i = 0;i <= k;++ i)sum = min(sum , dp[n][n - i]);
	printf("%d\n",sum);
	return ;
}
int main() {
	work();
	return 0;
}
posted @ 2022-01-23 11:36  ImALAS  阅读(60)  评论(0编辑  收藏  举报