思路:
dp题目,假贪心
定义dp状态为dp[i][j]表示不考虑当前站点i,那么前面的所有站点中去掉j个站点,得到的最小值。
那么转移为枚举i前面的所有站点j,然后假设j到i之间所有的站点都去掉,即去掉i-j-1个站点,那么多余的就从前j个站点中去掉p-(i-j-1)个转移,方程为:
其中j<i,k<p且k要大于i-j-1,dp[j][k-(i-j-1)]表示从前j个站点中去掉所多余的站点所得到的的最优解。
因为在输入中并没有说明最后终点是否存在站点,那么我们计算的时候就无法得之此时是否已经到达终点,那么我们可以给其添加上一个终点,那么每次的枚举i的时候,其中第i个站点对其的dp值是没有贡献的,因为以v[i]d[i]表示的在其后面才有贡献。
最后就是初始化问题,因为起点的站点是不能去掉的,因此我们需要初始化dp[1][i]=0,。
最后的dp[n+1][p]即为答案。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
const int N=505;
const int mod=1e9+7;
int n,m,p;
int d[N],v[N];
int dp[N][N];
void solve(){
cin>>n>>m>>p;
memset(dp,0x3f,sizeof(dp));
for(int i=1;i<=n;i++)cin>>d[i];
for(int i=1;i<=n;i++)cin>>v[i];
d[n+1]=m;
for(int i=0;i<=p;i++)dp[1][i]=0;
for(int i=2;i<=n+1;i++){
for(int j=1;j<i;j++){
for(int k=i-j-1;k<=p;k++){
dp[i][k]=min(dp[i][k],dp[j][k-(i-j-1)]+v[j]*(d[i]-d[j]));
}
}
}cout<<dp[n+1][p]<<"\n";
}
int main(){
int t=1;
//cin>>t;
while(t--){
solve();
}
}