P2466 [SDOI2008] Sue 的小球 ( 区间dp

#include 
using namespace std;
using PII = pair;
using ll  = long long;
using VI = vector;
using namespace std;

int n,s;
ll dp[1010][1010][2];
struct ball{
    int x,y,v;
}b[1010];

bool cmp(ball a,ball b){
    return a.x < b.x;
}
int sum[2010];
ll tot=0;
int main(){
    cin>>n>>s;
    for(int i = 1; i <= n; i++) cin>>b[i].x ;
    for(int i = 1; i <= n; i++) cin>>b[i].y,tot+=b[i].y ;
    for(int i = 1; i <= n; i++) cin>>b[i].v ;

    b[n+1] = {s,0,0};
    sort(b+1,b+1+n+1,cmp);
    for(int i = 1; i <= n+1; i++){
        sum[i] = sum[i-1] + b[i].v;
    }
    n++;
    int t;
    for(int i = 1;i <= n; i++) {
        if(b[i].x == s && b[i].y == 0 && b[i].v == 0) {
            t = i;
            break;
        }
    }
    memset(dp,0x3f,sizeof dp);
    dp[t][t][0] = 0;
    dp[t][t][1] = 0;
    for(int len = 2; len <= n ; len++){
        for(int i = 1;i + len -1 <= n; i++){
            int j = i + len - 1;
            dp[i][j][1] = min(dp[i][j-1][1] + 1ll*(b[j].x - b[j-1].x) * (sum[i-1] + sum[n] - sum[j-1]),
                              dp[i][j-1][0] + 1ll*(b[j].x - b[i].x) * (sum[i-1] + sum[n] - sum[j-1]) );
            dp[i][j][0] = min(dp[i+1][j][1] + 1ll*(b[j].x - b[i].x) * (sum[i] + sum[n] - sum[j]),
                              dp[i+1][j][0] + 1ll*(b[i+1].x - b[i].x) * (sum[i] + sum[n] - sum[j]));

        }
    }


    double v = (tot - min(dp[1][n][1] ,dp[1][n][0])) * 1.0 / 1000.0;
    printf("%.3f" , v);


}

f[i][j][0/1]  接了 i , j 段的所有球后停在 i or j,的最下损耗

你可能感兴趣的:(dp,算法,动态规划,图论)