洛谷P1043数字游戏

题目

区间DP,将\(maxn[i][j][k]\)表示为i到j区间内分为k个区间所得到的最大值,\(minn\)表示最小值。

然后可以得到状态转移方程:
\[maxn[i][j][k]= max(maxn[i][j][k],maxn[i][l][k-1]*(l到j的\%10后的和))\]

然后判断一下边界就能得到最终答案。

#include <bits/stdc++.h>
using namespace std;
int n, m, data[1001010];
int sum[111], ha[111][111];//每一段区间的和
int maxn[111][111][111], minn[111][111][111]; 
int ans1, ans2 = 2147483647;
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &data[i]);
        data[i + n] = data[i];
    }
    n *= 2;
    for (int i = 1; i <= n; i++)
        sum[i] = sum[i - 1] + data[i];
    memset(minn, 12, sizeof(minn));
    for (int i = 1; i <= n; i++)
        for (int j = i + 1; j <= n; j++)
            ha[i][j] = (sum[j] - sum[i] + 100000) % 10, maxn[i][j][1] = minn[i][j][1] = ha[i][j];
    for (int k = 2; k <= m; k++)
        for (int i = 1; i <= n; i++)
            for (int j = i + k - 1; j <= n; j++)
            {
                minn[i][j][k] = 214748367;
                for (int l = i + k - 2; l < j; l++)
                {
                    maxn[i][j][k] = max(maxn[i][l][k - 1] * ha[l][j], maxn[i][j][k]);
                    minn[i][j][k] = min(minn[i][l][k - 1] * ha[l][j], minn[i][j][k]);
                }
            }
    for (int i = 1; i <= n / 2; i++)
        ans1 = max(maxn[i][i + n / 2][m], ans1), ans2 = min(minn[i][i + n / 2][m], ans2);
    printf("%d\n%d", ans2, ans1);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/liuwenyao/p/11685976.html
今日推荐