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;
}