蓝桥云客 最大和
问题描述
小蓝在玩一个寻宝游戏,游戏在一条笔直的道路上进行,道路被分成了 n 个方格,依次编号 1 至 n,每个方格上都有一个宝物,宝物的分值是一个整数(包括正数、负数和零),当进入一个方格时即获得了方格中宝物的分值。小蓝可以获得的总分值是他从方格中获得的分值之和。
小蓝开始时站在方格 1 上并获得了方格 1 上宝物的分值,他要经过若干步 到达方格 n。
当小蓝站在方格 p 上时,他可以选择跳到 p+1 到 p+D(n−p) 这些方格 中的一个,其中 D(1)=1,D(x)(x>1) 定义为 x 的最小质因数。
给定每个方格中宝物的分值,请问小蓝能获得的最大总分值是多少。
输入格式
输入的第一行包含一个正整数 n。
第二行包含 n 个整数,依次表示每个方格中宝物的分值。
输出格式
输出一行包含一个整数,表示答案。
样例输入
5
1 -2 3 -1 5
样例输出
8
思路:
代码:
记忆化搜索
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N], mem[N], primes[N], min_primes[N], cnt, n;
bool st[N];
void get_primes(int n)
{
for (int i = 2; i <= n; i++)
{
if (!st[i])
{
primes[++cnt] = i;
min_primes[i] = i; // 记录质数的最小质因数是其本身
}
for (int j = 1; primes[j] <= n / i; j++)
{
st[primes[j] * i] = true;
min_primes[primes[j] * i] = primes[j]; // 记录合数的最小质因数
if (i % primes[j] == 0)
{
break;
}
}
}
}
// 计算 x 的最小质因数
int D(int x)
{
if (x == 1) return 1;
if (min_primes[x])
return min_primes[x];
else
{
cout << " 该数没有找到最小质因数 :" << endl;
return 1e9;
}
}
// 深度优先搜索并记忆化
int dfs(int x)
{
if (mem[x] != -1)
return mem[x];
if (x == n)
return a[x];
int sum = -1e9;
for (int i = x + 1; i <= x + D(n - x) && i <= n ; i++)
{
sum = max(sum, dfs(i));
}
mem[x] = sum + a[x];
return mem[x];
}
int main()
{
cin >> n;
get_primes(n);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
memset(mem, -1, sizeof(mem));
cout << dfs(1);
return 0;
}
dp:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N], dp[N], primes[N], cnt, n,min_primes[N];
bool st[N];
void get_primes(int n)
{
for (int i = 2; i <= n; i++)
{
if (!st[i])
{
primes[++cnt] = i;
min_primes[i] = i; // 记录质数的最小质因数是其本身
}
for (int j = 1; primes[j] <= n / i; j++)
{
st[primes[j] * i] = true;
min_primes[primes[j] * i] = primes[j]; // 记录合数的最小质因数
if (i % primes[j] == 0)
{
break;
}
}
}
}
// 计算 x 的最小质因数
int D(int x)
{
if (x == 1) return 1;
if (min_primes[x])
return min_primes[x];
else
{
cout << " 该数没有找到最小质因数 :" << endl;
return 1e9;
}
}
int main(void)
{
cin >> n;
get_primes(n);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
// 初始化 dp 数组
for (int i = 1; i <= n; i++)
{
dp[i] = -1e9;
}
dp[1] = a[1];
// 动态规划计算
for (int i = 2; i <= n; i++)
{
for (int j = 1; j < i; j++)
{
if (i <= j + D(n - j) && i <= n)
{
dp[i] = max(dp[i], dp[j] + a[i]);
}
}
}
cout << dp[n];
return 0;
}