思路是这样的:
设 fi,j,0/1 表示处理完第 i 个点到第 j 个点后,停在 i 点(0) ,或者停在 j 点的位置时花费的最小值。
转移方程是:
fi,j,0=min⎩⎨⎧fi+1,j,0+v(posi+1−posi)×Δfi+1,j,1+v(posj−posi)×Δ
fi,j,1=min⎩⎨⎧fi,j−1,0+v(posj−posi)×Δfi,j−1,1+v(posj−posj−1)×Δ
处理操作是把初始位置点也加进去,然后按照位置大小排序后进行区间DP。样例已过,但不知道哪里错了qwq,求大佬查错
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
const double INF=0x3f3f3f3f;
const int N=1e3+9;
const int M=1e3+9;
struct node{
double pos;//位置
double delt;//增长量
double once;//立刻修复的花费
}wal[N];
double sum[N];//前缀和
double tol;//一开始的总的立刻修理的花费
double v;//速度
int n,c;
double f[N][N][3];//修理完i-j区间停在了i(0)j(1)时的最小费用
int read()
{
int f=1,x=0;
char s=getchar();
while(s<'0'||s>'9')
{
if(s=='-')
f=-1;
s=getchar();
}
while(s>='0'&&s<='9')
{
x=(x<<1)+(x<<3)+(s^'0');
s=getchar();
}
return f*x;
}
bool cmp(node x,node y)
{
return x.pos<y.pos;
}
void prepare()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j][1]=f[i][j][0]=INF;//赋极大值
int now=0;
for(int i=1;i<=n;i++)
if(wal[i].pos==(double)c&&wal[i].once==0&&wal[i].delt==0)
{
now=i;
break;
}//找出起始点的位置;
for(int i=1;i<=n;i++)
tol+=wal[i].once; //直接把一开始的花费存到一起
f[now][now][1]=0;
f[now][now][0]=0;//预处理起始点
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+wal[i].delt;//前缀和
}
void DP()
{
for(int len=2;len<=n;len++)
for(int i=1;i-1+len<=n;i++)
{
int j=i-1+len;
f[i][j][0]=min(f[i+1][j][0]+(wal[i+1].pos-wal[i].pos)/v*(sum[n]-sum[j]+sum[i]),
f[i+1][j][1]+(wal[j].pos-wal[i].pos)/v*(sum[n]-sum[j]+sum[i]));
f[i][j][1]=min(f[i][j-1][1]+(wal[j].pos-wal[j-1].pos)/v*(sum[n]-sum[j-1]+sum[i-1]),
f[i][j-1][0]+(wal[j].pos-wal[i].pos)/v*(sum[n]-sum[j-1]+sum[i-1]));
// printf("f[%d][%d][0]= %lf\n",i,j,f[i][j][0]);
// printf("f[%d][%d][1]= %lf\n",i,j,f[i][j][1]);
}
return;
}
int main()
{
while(cin>>n)
{
scanf("%lf",&v);
//cout<<"v= "<<v<<endl;
c=read();
if(n==0) break;
for(int i=1;i<=n;i++)
scanf("%lf%lf%lf",&wal[i].pos,&wal[i].once,&wal[i].delt);
wal[++n].pos=double(c);//把起始点加进去
wal[n].once=0.0;
wal[n].delt=0.0;
sort(wal+1,wal+1+n,cmp);
prepare();
DP();
printf("%d\n",(int)tol+min((int)f[1][n][0],(int)f[1][n][1]));
}
return 0;
}