Codeforces 1016C Vasya And The Mushrooms

题目链接:http://codeforces.com/contest/1016/problem/C

题意:从左上角格子开始走,每次走一个临近的格子,速率为1,走过的格子取走所有的蘑菇,每个格子上的蘑菇有一个增长速率,问获得的最大的增长速率是多少

分析:dp。除了样例中给的两种走法,还有可能是两种走法的结合。预处理出来每次折线走法的每一个格子获得的速率值,绕圈走法左边的列相当于它右边的一列加上一个后缀和(因为走过一格后面的格子相当于时间多了1,加上增长速率和即可),为了保证获得的速率值最大,只能是先折线走再绕圈走,绕圈走可能是从上到下或者从下到上,类似处理即可,注意long long 。

代码:

#include
using namespace std;
const int maxn = 3e5 + 10;
typedef long long ll;
ll a[maxn],b[maxn];
ll S1[maxn],S2[maxn],S3[maxn],S4[maxn],SS[maxn];
int n;
void init1()//走折线,从上往下走
{
    for(int i = 1; i <= n; i++)
    {

        if(i % 2)
        {
            S1[i] = a[i] * (2 * i - 2);
            S1[i] += S1[i - 1];
            S2[i] = b[i] * (2 * i - 1);
            S2[i] += S1[i];
        }
        else
        {
            S2[i] = b[i] * (2 * i - 2);
            S2[i] += S2[i - 1];
            S1[i] = a[i] * (2 * i - 1);
            S1[i] += S2[i];
        }
    }
}
void init2()
{
    ll ans = 0;
    for(int i = n; i >= 1; i--)
    {
        ans += a[i] + b[i];
        SS[n - i + 1] = ans;
    }
}
void init3()//前面的由后面的转移过来,每次增加一个后缀和
{
    for(int i = n,l = 0; i >= 1; i--,l++)//从上到下
    {
        S3[i] = S3[i + 1] + SS[l] + b[i] * (2 * l + 1);
    }
    for(int i = n,l = 0; i >= 1; i--,l++)//从下到上
    {
        S4[i] = S4[i + 1] + SS[l] + a[i] * (2 * l + 1);
    }
}
int main()
{
    cin>>n;
    for(int i = 1; i <= n; i++)
    {
        cin>>a[i];
    }
    for(int i = 1; i <= n; i++)
    {
        cin>>b[i];
    }
    init1();
    init2();
    init3();
    ll ans = 0;
    ans = S3[1];
    for(int i = 1; i <= n; i++)
    {
        if(i % 2 == 0)
        {
           ans = max(ans,S1[i] + S3[i + 1] + (i * 2) * SS[n - i]);
        }
        else
        {
            ans = max(ans,S2[i] + S4[i + 1] + (i * 2) * SS[n - i]);
        }
    }
    cout<

 

你可能感兴趣的:(dp)