P2466 [SDOI2008] Sue 的小球

/*
XOY 一排点(xi,yi) 下降vi/s 从(x0,y0)出发 lft/rht
pre:按坐标xi排序
假设已经走了i-j 在决定走新点 时 可以去 i-1/j+1 现在的pos==i/j
正着 很难算贡献 收益max->损失min
->dp[i][j]:从(x0,y0) 走了i-j 位置i 损失min
-> f[i][j]:从(x0,y0) 走了i-j 位置j 损失min
考虑如何推
已经经过的时间会对对后面的 方程产生影响<---走过的点不会再走
--->已经经过的时间随时记录 posi->posj time+=(posj-posi)*未走过的总和
mem dp f -1
len:1-n
    i:1---n-len+1
        j:i+len-1---n
dp[i][j]=max(dp[i][j],dp[i+1][j]+(xi+1 -xi)*(sum(1,i)+sum(j+1,n))

*/
/*
3 0
-4 -2 2
22 30 26
1 9 8

0.000
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string.h>
#include<queue>
#include<vector>
#include<bits/stdc++.h>
#define ll long long
#define ddd printf("-----------------------\n");
using namespace std;
const int maxn=1e3 +10;
const int mod=998244353;
const int inf=0x3f3f3f3f;

struct node{
    int x,y,v;
}ball[maxn];

bool cmp(node a,node b){
    return a.x<b.x;
}

int n,x0;
int f[maxn][maxn],g[maxn][maxn],tot,pre[maxn];


int main()
{
    ios::sync_with_stdio(false);
    memset(f,inf,sizeof(f)),memset(g,inf,sizeof(g));
    
    cin>>n>>x0;
    for(int i=1;i<=n;i++) cin>>ball[i].x;
    for(int i=1;i<=n;i++) cin>>ball[i].y,tot+=ball[i].y;
    for(int i=1;i<=n;i++) cin>>ball[i].v;
    ball[++n]={x0,0,0};
    
    sort(ball+1,ball+1+n,cmp);
    for(int i=1;i<=n;i++) pre[i]=pre[i-1]+ball[i].v;
    for(int i=1;i<=n;i++) if(ball[i].x==x0&&ball[i].y==0&&ball[i].v==0) f[i][i]=g[i][i]=0;                           
     
    for(int len=2;len<=n;len++)
    {
        for(int i=1,j=i+len-1;i<=n&&j<=n;i++,j=i+len-1)
        {
            //int j=i+len-1;
            f[i][j]=min(f[i][j],f[i+1][j]+(ball[i+1].x-ball[i].x)*(pre[i]+pre[n]-pre[j]));
            f[i][j]=min(f[i][j],g[i+1][j]+(ball[j].x-ball[i].x)*(pre[i]+pre[n]-pre[j]));
            g[i][j]=min(g[i][j],g[i][j-1]+(ball[j].x-ball[j-1].x)*(pre[n]-pre[j-1]+pre[i-1]));
            g[i][j]=min(g[i][j],f[i][j-1]+(ball[j].x-ball[i].x)*(pre[n]-pre[j-1]+pre[i-1]));
        }
    }
    
    printf("%.3lf\n",1.00*(tot-min(f[1][n],g[1][n]))/1000.00);
    return 0;
}
#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=1e3+10;

int n,sx,w[N][N],sum1[N],sum2[N],f[N][N][2];
struct node
{
    int x,y,v;
    friend bool operator < (const node &A,const node &B){return A.x<B.x;}
}a[N];

signed main()
{
    scanf("%lld%lld",&n,&sx);
    for(int i=1; i<=n; i++)
        scanf("%lld",&a[i].x);
    for(int i=1; i<=n; i++)
        scanf("%lld",&a[i].y);
    for(int i=1; i<=n; i++)
        scanf("%lld",&a[i].v);
    a[++n]={sx,0,0};

    sort(a+1,a+1+n);

    for(int i=1; i<=n; i++)
        sum1[i]=sum1[i-1]+a[i].v;
    for(int i=n; i>=1; i--)
        sum2[i]=sum2[i+1]+a[i].v;
    int x;
    for(int i=1; i<=n; i++)
    {
        for(int j=i; j<=n; j++)
            w[i][j]=sum1[i-1]+sum2[j+1];
        if(a[i].x==sx && a[i].y==0 && a[i].v==0)
            x=i;
    }

    memset(f,~0x7f,sizeof(f));
    f[x][x][0]=f[x][x][1]=0;    
    for(int len=2; len<=n; len++)
    {
        for(int i=1; i+len-1<=n; i++)
        {
            int j=i+len-1;
            f[i][j][0]=max(f[i+1][j][0]-w[i+1][j]*(a[i+1].x-a[i].x),f[i+1][j][1]-w[i+1][j]*(a[j].x-a[i].x))+a[i].y;
            f[i][j][1]=max(f[i][j-1][1]-w[i][j-1]*(a[j].x-a[j-1].x),f[i][j-1][0]-w[i][j-1]*(a[j].x-a[i].x))+a[j].y;
            // cout<<i<<" "<<j<<" "<<a[i].y<<" "<<max(f[i][j][0],f[i][j][1])<<endl;
        }    
    }

    printf("%.3lf\n",1.0000*max(f[1][n][0],f[1][n][1])/1000.0000);

    
    return 0;
}

/*
1 0
0 5 5
*/
AC

 

posted @ 2023-11-13 05:04  JMXZ  阅读(14)  评论(0)    收藏  举报