题目链接:http://acm.hust.edu.cn/vjudge/problem/36139
题意:一条直线上有n个点需要修理,每个点有一个修理费用ci和单位时间增加的费用di,如果在时刻t去修理,那么此点的费用为t*di+ci。给出起始坐标,求修复完全部点的最小话费。
思路:设f[i][j][k]为修复完区间[i,j]内的点且在当前区间的左端点(k=0)/右端点(k=1)时的最小花费,每一次前往一个点去修理需要花费时间t,那么所有还没被修理过的点就会产生∑di * t的额外花费,我们将某个点的花费按照时间拆开分段累加,这样就可以计算了。当前在某个区间[i,j]可以去i-1点修理或i+1点修理。
若向左走dp(i-1,j,0) = min( dp(i,j,0) + t(i->i+1) * ∑di , dp(i,j,1) + t(j->i+1) * ∑di )。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;
#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)
#define Clean(x,y) memset(x,y,sizeof(x))
#define LL long long
#define ULL unsigned long long
#define inf 1000000001
const int maxn = 1009;
struct node
{
int pos;
int c;
int add;
}p[maxn];
int n,v,stpos,st;
double dp[maxn][maxn][2];
LL sum[maxn];
bool cmp( node x , node y )
{
return x.pos < y.pos;
}
void init()
{
rep(i,1,n) scanf("%d%d%d",&p[i].pos,&p[i].c,&p[i].add);
n++;
p[n].pos = stpos;
p[n].add = p[n].c = 0;
sort( p + 1 , p + 1 + n , cmp );
Clean(sum,0);
rep(i,1,n)
sum[i] = sum[i-1] + p[i].add;
}
double cal( int l , int r ) //计算除去[l,r]范围内的∑di
{
return sum[l-1] + sum[n] - sum[r];
}
double cost( int x1 , int x2 ) //两点之间需要用的时间
{
return (double)abs( p[x1].pos - p[x2].pos ) / (double)v;
}
void solve()
{
rep(i,1,n)
if ( p[i].pos == stpos )
{
st = i;
break;
}
rep(i,1,n)
if ( i == st ) dp[i][i][0] = dp[i][i][1] = 0;
else dp[i][i][0] = dp[i][i][1] = inf;
rep(len,1,n-1)
rep(l,1,n-len)
{
int r = l + len;
double ex = cal( l+1 , r );
dp[l][r][0] = min( dp[l+1][r][0] + ex * cost( l+1 , l ) , dp[l+1][r][1] + ex * cost( r , l ) );
ex = cal( l , r - 1 );
dp[l][r][1] = min( dp[l][r-1][0] + ex * cost( l , r ) , dp[l][r-1][1] + ex * cost( r - 1 , r ) );
}
double ans = min( dp[1][n][0] , dp[1][n][1] );
rep(i,1,n) ans += p[i].c;
printf("%d\n",(int)ans);
}
int main()
{
while(cin>>n>>v>>stpos)
{
if ( n + v + stpos == 0 ) break;
init();
solve();
}
return 0;
}