【洛谷 p2672】推销员

推销员【题目链接】

好了为了凑字数先把题目复制一下:

好了题解第一篇正解:

首先输入,莫得什么好说的:

 scanf("%d",&n);
    for (int i=1;i<=n;i++)
        scanf("%d",&a[i].s);
    for (int i=1;i<=n;i++)
        scanf("%d",&a[i].v);

然后是思路:

对于每一个x,我们有两种选择:

①选择前x个a值最大的;

②选择前x-1个a值最大的,再在x~n中选择一个s[i]*2+a[i]最大的。

先按照a从大到小排序;

然后数组q[i]记录前i项的a的和;

for (int i=1;i<=n;i++)
        q[i]=q[i-1]+a[i].v;

数组h[i]记录a[i]*2+s[i]后i项的最大值(也就是为了应对情况②)

for (int i=n;i>=1;i--)
        h[i]=max(h[i+1],2*a[i].s+a[i].v);

数组qm[i]记录前i项的s的最大值;

for (int i=1;i<=n;i++)
        qm[i]=max(qm[i-1],a[i].s);

答案就是max(q[x]+2*qm[x],q[x-1]+h[x])

对于为什么只取一个后i个,你想啊,只有最远到达的地点的s会对最终答案产生影响,而且其实这里q[x-1]+h[x]并不一定是实际答案,如果前x-1个中s有一个sd大于我们h[i]中取的si,我们本应该用sd来计算答案,但这个题是用si来计算,这样不会对真实的答案造成影响。

 

posted @ 2019-07-03 09:50  Sweetness  阅读(186)  评论(0)    收藏  举报