状态表示很难,因为走的路线是来回路,要么往左走,要么往右走,而且只要是经过的坏点,都会被修缮。
所以被修缮的点的范围是从起点开始逐渐扩大而不会缩小的。
dp[le][ri][0]表示已经修完了[le,ri]区间内的点,现在在le点处。
dp[le][ri][1]表示已经修完了[le,ri]区间内的点,现在在ri点处。
因为修完[le,ri]区间内的点后 一定在这两点之一。
之后不是往左走,就是往右走,但是因为用的方法是递推,我们每次只用向左或向右走一步。
/**==========================================
* This is a solution for ACM/ICPC problem
*
* @source:uva 1336 Fixing the Great Wall
* @type:
* @author: wust_ysk
* @blog: http://blog.csdn.net/yskyskyer123
* @email: 2530094312@qq.com
*===========================================*/
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define eps 1e-10
using namespace std;
typedef long long ll;
const double inf=1e15;
const int maxn= 1000 ;
//const int maxV=12 ;
int n,startPos;
double dp[maxn+4][maxn+4][2];
double v;
int sum[maxn+4];
struct Node
{
int pos,cost,add;
bool operator<(const Node y)const
{
return pos<y.pos;
}
}a[maxn+5];
int main()
{
int x;
while(~scanf("%d%lf%d",&n,&v,&startPos)&&(n||v||startPos ))
{
a[0].pos=startPos;
a[0].add=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i].pos,&a[i].cost,&a[i].add);
}
sort(a,a+1+n);
for(int i=0;i<=n;i++)
{
if(!i) sum[i]=a[i].add;
else sum[i]=sum[i-1]+a[i].add;
if(a[i].pos==startPos)
{
x=i;
}
}
for(int i=0;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
dp[i][j][0]=dp[i][j][1]=inf;
}
}
dp[x][x][0]=dp[x][x][1]=0;
for(int add=0;add<n;add++)
{
for(int st=0 ;st+add<=n ;st++)
{
int ed=st+add;
for(int k=0;k<=1;k++) if(dp[st][ed][k]!=inf)
{
int p=k?ed :st;
if(st-1>=0)
{
int des=st-1;
double ans=dp[st][ed][k];
double t= (a[p].pos-a[des].pos)/v;
ans+= a[des].cost+ t*( sum[n]-sum[ed]+sum[st-1] );
dp[st-1][ed][0]=min(dp[st-1][ed][0],ans);
}
if(ed+1<=n)
{
int des=ed+1;
double ans=dp[st][ed][k];
double t= (a[des].pos-a[p].pos)/v;
ans+= a[des].cost+ t*( sum[n]-sum[ed]+ (st-1>=0?sum[st-1]:0) );
dp[st][ed+1][1]=min(dp[st][ed+1][1],ans);
}
}
}
}
ll ans= min(dp[0][n][0],dp[0][n][1])+eps;//加不加eps均可AC
printf("%lld\n",ans);
}
return 0;
}
/*
3 1 1000
1010 0 100
998 0 300
996 0 3
3 1 1000
1010 0 100
998 0 3
996 0 3
0 0 0
*/