luogu T40984Chino的成绩

时间:2022-05-22 13:08:53

Chino的成绩

题目描述

Chino非常注重自己的成绩

Chino有m种方式给自己增加rp以增加成绩,她的每种增加rp的方式都有n个阶段,第i种的第j个阶段增加的rp表示为Aij​,表示连续进行了j天第i种增加rp的方式

Chino连续进行同一种方式,效果可能更好也可能更差,她想要知道在n天里能获得的最大rp,你能帮帮可爱的Chino吗?

输入输出格式

输入格式:

第一行,两个正整数n,m

接下来m行,第i+1行为n个整数A[i][1]~A[i][n]​

输出格式:

一行一个数,最大的rp

输入输出样例

输入样例#1:
3 3
3 2 1
3 1 1
3 3 1
输出样例#1:
9
输入样例#2:
3 3
3 2 1
3 5 2
4 1 1
输出样例#2:
12

说明

本题分为3个Subtask

第一个Subtask,2组数据 ,保证n \leq 50n≤50, m \leq 5000m≤5000, a_i \leq 1e9ai​≤1e9

对于第二个Subtask,4组数据,保证n \leq 70n≤70, m \leq 10000m≤10000, a_i \leq 1e9ai​≤1e9

对于第三个Subtask,4组数据,保证n \leq 100n≤100, m \leq 5000m≤5000, a_i \leq 1e9ai​≤1e9

其中每组数据4分,对于每个Subtask及其中的每个数据点,取分数和。

样例解释1

第 1 天进行第 1 项活动,获得 A11​=3 点rp。

第 2 天进行第 2 项活动,获得 A21​=3 点rp。

第 3 天进行第 1 项活动,获得 A11​=3 点rp。

样例解释2

第 1 天进行第 2 项活动,获得 A21​=3 点rp。

第 2 天进行第 2 项活动,获得 A22​=5 点rp(因为已经连续进行了 2 次第 2 项活动,因而是 A22​ 而不是 A21​。

第 3 天进行第 3 项活动,获得 A31​=4 点rp。

这个坑留了好久吧,终于回来填坑了

sol:

首先如果a = {3, 2, 1}, 如果取三天只能是6, 9是不合法的,这个要搞清楚

所以当前这个方案取了几天一定要有

f(i, j)表示到第i天,以第j中方案结尾的最大rp

g(i, j)记录当前这个方案取了几天

1、继续采用当前的方案
f(i,j)=f(i−1,j)+a[j][g(i−1,j)+1])
g(i,j)=g(i−1,j)+1
2、更换方案
f(i,j)=max(f(i−1,k)+a[j][1])(k!=j)
g(i,j)=1

然后这个k可以用前缀和处理掉,(滚存一下)

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n, m, a[][];
int f[][], g[][];
int pre[], suf[];
int main()
{
scanf("%d%d", &n, &m);
for(int i = ; i <= m; i++)
for(int j = ; j <= n; j++)
scanf("%d", &a[i][j]);
memset(f, , sizeof f);
memset(g, , sizeof g);
for(int i = ; i <= n; i++)
{
for(int j = ; j <= m; j++)
{
if (f[i - ][j] + a[j][g[i - ][j] + ] > max(pre[j - ], suf[j + ]) + a[j][])
{
f[i][j] = f[i - ][j] + a[j][g[i - ][j] + ];
g[i][j] = g[i - ][j] + ;
}
else
{
f[i][j] = max(pre[j - ], suf[j + ]) + a[j][];
g[i][j] = ;
}
}
memset(pre, , sizeof pre);
memset(suf, , sizeof suf);
for(int j = ; j <= m; j++)
pre[j] = max(pre[j - ], f[i][j]);
for(int j = m; j >= ; j--)
suf[j] = max(suf[j + ], f[i][j]);
}
int ans = ;
for(int i = ; i <= m; i++)
ans = max(ans, f[n][i]);
printf("%d\n", ans);
}