NKOJ P2455 [东方幻想乡]【动态规划】

题外话:

这道题….考试的时候我居然没有做出来….没有做出来….我硬生生想了半天二维状态我推不走…..然后正解是一维…..也确实不难…..这就很难受了…..我已经好几道一维 D P 我完全想成二维推不走了…..

其实就是一个简单的动态规划了….写这篇题解来悔过一下吧…..
首先我们要求出每个点过平行于已知直线的在y轴上的交点,不妨设已知直线的斜率为K,某个点的坐标为 P Q ,那么过这个点的平行于已知直线的在y轴上的交点的坐标为 0 Q K P ,然后我们按照这个坐标排个序就可以了,不妨从小到大排序..

D P [ I ] 表示前 I 个点可以得到的最大贡献,那么很显然的状态转移方程….如下:

D P [ I ] = m a x ( D P [ I ] ( V a l [ I ] V a l [ J ] ) ( M u l [ I ] M u l [ J ] ) I J )

参考代码:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define DB double
#define SG string
#define LL long long
using namespace std;
const LL Max=3e6+5;
const DB Pi=acos(-1);
struct Node{
    DB K,X,Y,Val,Mul;
}G[Max];
LL N,M;
DB DP[Max],Val[Max],Mul[Max];
bool Cmp(Node P,Node Q){
    return P.K<Q.K;
}
int main(){
    LL I,J;DB K;
    scanf("%lld",&N);
    for(I=1;I<=N;I++){
        scanf("%lf%lf%lf%lf",&G[I].X,&G[I].Y,&G[I].Val,&G[I].Mul);
    }scanf("%lld",&M);K=tan((DB)(Pi*M/180.0));
    for(I=1;I<=N;I++){
        G[I].K=G[I].Y-K*G[I].X;
    }
    sort(G+1,G+1+N,Cmp);
    for(I=1;I<=N;I++){
        Val[I]=Val[I-1]+G[I].Val;
        Mul[I]=Mul[I-1]+G[I].Mul;
    }
    for(I=1;I<=N;I++){
        for(J=I-1;J>=0;J--){
            if(DP[I]<DP[J]+(Val[I]-Val[J])*(Mul[I]-Mul[J])/(I-J)){
                DP[I]=DP[J]+(Val[I]-Val[J])*(Mul[I]-Mul[J])/(I-J);
            }
        }
    }
    printf("%.3lf",DP[N]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/80977060
今日推荐