UVA 1336 Fixing the Great Wall

題目鏈接: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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章