推销员【题目链接】

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

【洛谷 p2672】推销员-LMLPHP

【洛谷 p2672】推销员-LMLPHP

【洛谷 p2672】推销员-LMLPHP

好了题解第一篇正解:

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

 scanf("%d",&n);
for (int i=;i<=n;i++)
scanf("%d",&a[i].s);
for (int i=;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=;i<=n;i++)
q[i]=q[i-]+a[i].v;

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

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

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

for (int i=;i<=n;i++)
qm[i]=max(qm[i-],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来计算,这样不会对真实的答案造成影响。

05-28 03:59