签到题
经典斐波那契。只是多了一个参数,本蒟蒻都能秒,就不写题解了
B题
小T 负责修复一个由字母和未知字符组成的编码串,其中未知字符用 ? 表示。他需要将所有的 ? 替换为小写字母,要求修复后的编码串中相邻的字符不能相同。而原本的已知字符保持不变,并且这些字符之间不会出现连续重复的情况。 你的任务是帮助小T完成替换,确保最终的编码串符合要求,并且如果有多个符合条件的修复方案,返回字典序最小的那一个。
练回溯的好题目 感觉B题思维量是最大的,递归链和过程得慢慢理清楚 可能是本蒟蒻递归功底太菜orz
#include <iostream>
#include <string>
using namespace std;
//检查函数
bool isValid(string& s , int index, char c){
if(index > 0 && s[index - 1] == c) return false; //
if(index < s.size() - 1 && s[index + 1] != '?' && s[index + 1] == c) return false; // 剪枝 注意如果换完还相等也不行
return true;
}
// 核心的回溯函数
bool backtracking(string& s, int index) {
if (index == s.size()) return true; // 回溯结束条件 遍历到了最后一个字符
if (s[index] != '?') return backtracking(s, index + 1);
string hash = "abcdefghijklmnopqrstuvwxyz"; //开一个字母表从前往后遍历,保证字符大小最小
for (char c : hash) {
if (isValid(s, index, c)) {
s[index] = c;
if (backtracking(s, index + 1)) return true;
s[index] = '?';// 如果返回的是false,则说明总的结果不成立,则回溯
}
}
return false;
}
string solution(std::string s) {
backtracking(s, 0);
return s;
}
int main() {
cout << (solution("?ab") == "bab") << endl;
cout << (solution("v?yz?") == "vayza") << endl;
cout << (solution("?xyz??") == "axyzab") << endl;
cout << (solution("b??b?") == "bacba") << endl;
cout << (solution("???z") == "abaz") << endl;
return 0;
}
C题
经典的二维前缀和
在一个遥远的魔法村庄里,年轻的巫师小雪正在探索一个神秘的宝石矩阵 gems,这个矩阵的大小为 m x n,其中每个宝石都有一个特定的能量值。同时,她得到了一个能量上限 M,她希望找到一个正方形区域,使得该区域内宝石的能量总和不超过 M,并且这个正方形的边长尽可能大。 请你帮助小雪计算出满足这些条件的最大正方形边长。如果没有符合条件的正方形区域,返回 0。
#include<bits/stdc++.h>
using namespace std;
int max_square_size(vector<vector<int>>& gems, int M) {
int m = gems.size();
int n = gems[0].size();
vector<vector<int>> prefix_sum(m + 1, vector<int>(n + 1, 0));
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
prefix_sum[i][j] = prefix_sum[i - 1][j] + prefix_sum[i][j - 1] - prefix_sum[i - 1][j - 1] + gems[i - 1][j - 1];
}
}
int max_side = 0;
// 三层for循环遍历找最长的边,
for (int side = 1; side <= min(m, n); side++) {
for (int i = 1; i <= m - side + 1; i++) {
for (int j = 1; j <= n - side + 1; j++) {
int sub_sum = prefix_sum[i + side - 1][j + side - 1] -
prefix_sum[i - 1][j + side - 1] - prefix_sum[i + side - 1][j - 1] +
prefix_sum[i - 1][j - 1];
if (sub_sum <= M) {
max_side = side;
}
}
}
}
return max_side;
}
int main() {
//todo 输入样例
}
D题
模板dp
使用滚动数组,将空间复杂度优化到n
在一个神秘的竞技场中,勇敢的探险者小青拥有两个宝箱:一个宝箱里装满了 n 个金银珠宝的数值,另一个则是一个包含 m 个神秘符文的序列。小青面临着一个挑战:在接下来的 m 轮中,他必须在这两者之间做出明智的选择,以获得最高的财富。 在每一轮(第 i 轮)中,小青可以选择从宝箱的最上面或最下面取出一个珠宝 x。然后,他会将这个珠宝的价值乘以对应的符文 c[i],并把结果累加到他的总财富中。被取出的珠宝将从宝箱中消失,接着小青会继续下一轮操作,直到完成 m 轮。 你的任务是帮助小青计算,在完成 m 轮挑战后,他可以获得的最高财富是多少。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int solution(vector<int> stones, vector<int> c) {
int n = stones.size(), m = c.size();
vector<int> dp(n + 1, 0), prev(n + 1, 0);
for (int i = 1; i <= m; ++i) {
for (int j = i; j >= 0; --j) {
int left = (j > 0) ? prev[j - 1] + stones[j - 1] * c[i - 1] : INT_MIN;
int right = (j < i) ? prev[j] + stones[n - (i - j)] * c[i - 1] : INT_MIN;
dp[j] = max(left, right);
}
swap(dp, prev);
}
return *max_element(prev.begin(), prev.begin() + m + 1);
}
int main() {
cout << (solution({-3, 4, 5}, {2, -1, 3}) == 25) << endl;
cout << (solution({6, -7, 1}, {4, -3}) == 45) << endl;
cout << (solution({3, 5, -2, 9}, {1, 3, -5}) == 40) << endl;
return 0;
}