OJ笔试强训_25至48天_每天三道OJ
Day25(30分钟全AC,有一道01背包)
BC145 [NOIP2008]笨小猴
[NOIP2008]笨小猴_牛客题霸_牛客网
#include <climits>
#include <cmath>
#include <iostream>
#include <vector>
using namespace std;bool isPrime(int x) // Day25_1
{if(x < 2)return false;for(int i = 2; i <= sqrt(x); ++i){if(x % i == 0)return false;}return true;
}int main()
{vector<int> hash(150, 0);string str;cin >> str;for(auto& e : str){hash[e]++;}int minn = INT_MAX, maxn = INT_MIN;for(auto& e : hash){if(e != 0)minn = min(minn, e);maxn = max(maxn, e);}// cout << maxn << " " << minn << endl;// if(minn == 0 && maxn != minn)// minn = 1;if(isPrime(maxn - minn))cout << "Lucky Word" << endl << maxn - minn << endl;elsecout << "No Answer" << endl << 0 << endl;return 0;
}
NC383主持人调度(一)
主持人调度(一)_牛客题霸_牛客网
class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param schedule int整型vector<vector<>> * @return bool布尔型*/bool hostschedule(vector<vector<int> >& schedule) {// Day25_2_看有没有重合的区间sort(schedule.begin(), schedule.end());int sz = schedule.size();for(int i = 1; i < sz; ++i){if(schedule[i][0] < schedule[i - 1][1])return false;}return true;}
};
DP45分割等和子集
#include <iostream>
#include <vector>
using namespace std;int main() // 挑选一些数,使这些数的和等于数组和的一半,01背包
{int n = 0;cin >> n;vector<int> nums(n + 1);int sum = 0;for(int i = 1; i <= n; ++i){cin >> nums[i];sum += nums[i];}if(sum % 2 == 1){cout << "false" << endl;return 0;}sum /= 2;vector<int> dp(sum + 1); // 滚动数组优化for(int i = 1; i <= n; ++i){for(int j = sum; j >= nums[i]; --j){dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);if(dp[j] == sum){cout << "true" << endl;return 0;}}}cout << "false" << endl;return 0;
}// #include <iostream>
// #include <vector>
// using namespace std;// int main() // 挑选一些数,使这些数的和等于数组和的一半,01背包
// {
// int n = 0;
// cin >> n;
// vector<int> nums(n + 1);
// int sum = 0;
// for(int i = 1; i <= n; ++i)
// {
// cin >> nums[i];
// sum += nums[i];
// }
// if(sum % 2 == 1)
// {
// cout << "false" << endl;
// return 0;
// }
// sum /= 2;
// vector<vector<int>> dp(n + 1, vector<int>(sum + 1));
// for(int i = 1; i <= n; ++i)
// {
// for(int j = 0; j <= sum; ++j)
// {
// dp[i][j] = dp[i - 1][j];
// if(j >= nums[i])
// dp[i][j] = max(dp[i][j], dp[i - 1][j - nums[i]] + nums[i]);
// if(dp[i][j] == sum)
// {
// cout << "true" << endl;
// return 0;
// }
// }
// }
// cout << "false" << endl;
// return 0;
// }
Day26(50分钟被第三题卡了,没写出来,第二题卡了一点)
小红的ABC(暴力/找规律)
小红的ABC (nowcoder.com)
(暴力解法:)
#include <climits>
#include <iostream>
using namespace std;
string str;bool isPal(int left, int right)
{while(left < right){if(str[left] == str[right])++left, --right;elsereturn false;}return true;
}
int main() // Day_26_1最短回文子串,滑动窗口? or dp? or 暴力?
{cin >> str; // 暴力int n = str.size(), res = INT_MAX;for(int i = 0; i < n; ++i){for(int j = i + 1; j < n; ++j){if(isPal(i, j))res = min(res, j - i + 1);}}res = res == INT_MAX ? -1 : res;cout << res << endl;return 0;
}
找规律解法:
#include <iostream>
using namespace std;int main() // Day_26_1最短回文子串,滑动窗口? or dp? or 暴力?
{string str;cin >> str;int n = str.size(), res = -1;for(int i = 0; i < n; ++i){if(i - 1 < n && str[i] == str[i + 1]){res = 2;break;}if(i - 2 < n && str[i] == str[i + 2]){res = 3;}}cout << res << endl;return 0;
}
DP23不相邻取数(打家劫舍dp)
不相邻取数_牛客题霸_牛客网
错解:以为只有两种选法emmmm,过了百分之70的用例,还以为溢出了,可以选相邻距离大于2的!!!!!所以是打家劫舍问题dp
#include <iostream>
#include <vector>
using namespace std;#define int long longsigned main() // Day26_2_不相邻取数_取大的,且正整数,从0或1开始取
{int n = 0;cin >> n;vector<int> arr(n + 7);for(int i = 0; i < n; ++i){cin >> arr[i];}int sum1 = 0, sum2 = 0;if(n % 2 == 1){sum1 += arr[n - 1];n -= 1;}for(int i = 0; i <= n - 2; i += 2) // 注意i+=2和开long long{sum1 += arr[i]; // 大数加法?sum2 += arr[i + 1];}cout << max(sum1, sum2) << endl;return 0;
}
正解:打家劫舍问题dp
#include <iostream>
#include <vector>
using namespace std;int main() // Day26_2_不相邻取数_打家劫舍dp
{int n = 0;cin >> n;vector<int> arr(n + 1);for(int i = 1; i <= n; ++i){cin >> arr[i];}vector<int> g(n + 1), f(n + 1); // 选和不选for(int i = 1; i <= n; ++i){f[i] = g[i - 1] + arr[i];g[i] = max(f[i - 1], g[i - 1]);}cout << max(g[n], f[n]) << endl;return 0;
}
空调遥控(排序+二分/滑动窗口)
空调遥控 (nowcoder.com)
原暴力代码:?(以为是k没给范围错的,也没报超时,看了正解改了正确的k就报超时了,k的范围也不知道为什么是2到n)
#include <algorithm>
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
#define int long longsigned main() // Day_26_3空调遥控_暴力不行,排序+二分?
{// abs(e - k) <= p// if(e >= k) e - k <= p, e - p <= k 无语// if(e < k) k - e <= p, p - e >= kint n = 0, p = 0;cin >> n >> p;vector<int> arr(n);int arrMIN = INT_MAX, arrMAX = INT_MIN;for(int i = 0; i < n; ++i){cin >> arr[i];// arrMIN = min(arrMIN, arr[i]);// arrMAX = max(arrMAX, arr[i]);}// sort(arr.begin(), arr.end());int res = INT_MIN;for(int k = -100; k < 100; ++k){int cnt = 0;for(auto& e : arr){if(abs(e - k) <= p)++cnt;}// cout << k << " " << cnt << endl;res = max(res, cnt);}cout << res << endl;return 0;
}
排序+二分
#include <algorithm>
#include <iostream>
#include <vector>
#include <climits>
using namespace std;signed main() // Day_26_3空调遥控_暴力不行,排序+二分?
{// abs(e - k) <= p// if(e >= k) e - k <= p, e - p <= k 无语// if(e < k) k - e <= p, p - e >= kint n = 0, p = 0;cin >> n >> p;vector<int> arr(n);int arrMIN = INT_MAX, arrMAX = INT_MIN;for(int i = 0; i < n; ++i){cin >> arr[i];// arrMIN = min(arrMIN, arr[i]);// arrMAX = max(arrMAX, arr[i]);}sort(arr.begin(), arr.end());int res = INT_MIN;//cout << target1 << " " << target2 << endl;for(int k = 2; k <= n; ++k) // k的范围怎么知道的。。。{int target1 = k - p, target2 = k + p;auto left = lower_bound(arr.begin(), arr.end(), target1); // 找大于等于target1的左端点auto right = upper_bound(arr.begin(), arr.end(), target2);int len = right - left;//cout << len << " ";//cout << *left << " " << *right << endl;res = max(res, len);}cout << res << endl;return 0;
}
排序+滑动窗口
#include <algorithm>
#include <iostream>
#include <vector>
#include <climits>
using namespace std;signed main() // Day_26_3空调遥控_暴力不行,排序+二分/滑动窗口
{int n = 0, p = 0;cin >> n >> p;vector<int> arr(n);for(int i = 0; i < n; ++i){cin >> arr[i];}sort(arr.begin(), arr.end());int res = INT_MIN;int left = 0, right = 0;while(right < n){while(arr[right] - arr[left] > 2 * p){++left;}res = max(res, right - left + 1);++right;}cout << res << endl;return 0;
}
Day27(三道题都是过百分之60)
kotori和气球(排列组合)
kotori和气球 (nowcoder.com)
#include <iostream>
using namespace std;int main() // Day27_1_dp?
{int n = 0, m = 0;cin >> n >> m;long long cnt = n;// for(int i = m; i <= n; ++i)// {// cnt *= i;// }/*while(m--){cnt *= n;--n;}*/while(--m) // n * n - 1 * n - 1 ...{cnt *= n - 1;cnt %= 109;}cnt %= 109;cout << cnt << endl;return 0;
}
/*
3 2
1 2 3
12 13
21 23
31 324 2
1 2 3 4
12 13 14
21 23 24
31 32 34
41 42 43*/
AB20走迷宫(bfs里的n和m写反了,且可以用cnt/dist数组直接包含vis数组的作用)
走迷宫_牛客题霸_牛客网 (nowcoder.com)
#include <iostream>
#include <queue>
#include <utility>
#include <vector>
using namespace std;int n = 0, m = 0;
int x1, y1, x2, y2;
int dx[4] = {0, 0, -1, 1};
int dy[4] = {1, -1, 0, 0};
bool vis[1007][1007];void bfs(vector<vector<char>>& vv, vector<vector<int>>& cnt)
{queue<pair<int, int>> q;q.push({x1, y1});vis[x1][y1] = true;while(q.size()){auto[a, b] = q.front();q.pop();if(a == x2 && b == y2)return;for(int i = 0; i < 4; ++i){int x = dx[i] + a, y = dy[i] + b;// cout << x << " " << y << endl;if(x <= n && x > 0 && y <= m && y > 0 && !vis[x][y] && vv[x][y] == '.'){q.push({x, y});vis[x][y] = true;cnt[x][y] = cnt[a][b] + 1;// cout << x << " " << y << endl;// cout << cnt << endl;}}}
}signed main() // Day27_2_bfs
{cin >> n >> m;cin >> x1 >> y1 >> x2 >> y2;vector<vector<char>> vv(n + 1, vector<char>(m + 1));vector<vector<int>> cnt(n + 1, vector<int>(m + 1));for(int i = 1; i <= n; ++i){for(int j = 1; j <= m; ++j){cin >> vv[i][j];}}if(vv[x1][y1] == '*' || vv[x2][y2] == '*'){cout << -1 << endl;return 0;}bfs(vv, cnt);// for(int i = 1; i <= n; ++i)// {// for(int j = 1; j <= m; ++j)// {// cout << cnt[i][j] << " ";// }// cout << endl;// }if(cnt[x2][y2] == 0)cout << -1 << endl;elsecout << cnt[x2][y2] << endl;return 0;
}
NC147主持人调度(二)(一开始push零改成INT_MIN)
主持人调度(二)_牛客题霸_牛客网 (nowcoder.com)
class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** 计算成功举办活动需要多少名主持人* @param n int整型 有n个活动* @param startEnd int整型vector<vector<>> startEnd[i][0]用于表示第i个活动的开始时间,startEnd[i][1]表示第i个活动的结束时间* @return int整型*/int minmumNumberOfHost(int n, vector<vector<int> >& startEnd) {sort(startEnd.begin(), startEnd.end());priority_queue<int, vector<int>, greater<int>> res; // 存储每个主持人的结束时间res.push(INT_MIN); // 法二,用堆优化,注意一开始push INT_MIN!!!!!!不能是0for(int i = 0; i < n; ++i){if(res.top() <= startEnd[i][0]){res.pop();res.push(startEnd[i][1]);}else{res.push(startEnd[i][1]);}}return res.size();}
};/*int minmumNumberOfHost(int n, vector<vector<int> >& startEnd) {sort(startEnd.begin(), startEnd.end());vector<int> res; // 存储每个主持人的结束时间res.push_back(INT_MIN); // 法一,注意一开始push_back INT_MIN,不能是0for(int i = 0; i < n; ++i){// if(startEnd[i][0] < startEnd[i - 1][i])// ++res;bool flag = false;for(auto& e : res) // 找一个主持人去主持{if(e <= startEnd[i][0]){e = startEnd[i][1];flag = true;break;}}if(flag == false){res.push_back(startEnd[i][1]);}}return res.size();}
};
*/
Day28(急得上课,写了十分钟)
游游的重组偶数
游游的重组偶数__牛客网
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;int main()
{long long q = 0;cin >> q;while(q--){long long tmp = 0;cin >> tmp;string str = to_string(tmp);bool flag = false;sort(str.begin(), str.end()); // 忘记排序了,且没处理前导零do{int x = atoi(str.c_str());if(x % 2 == 0){cout << x << endl;flag = true;break;}}while (next_permutation(str.begin(), str.end()));if(flag == false)cout << -1 << endl;}return 0;
}
个位是偶数就是偶数!!!!所以依次交换到个位就行
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;int main()
{long long q = 0;cin >> q;while(q--){long long tmp = 0;cin >> tmp;string str = to_string(tmp);bool flag = false;sort(str.begin(), str.end()); // 忘记排序了,且没处理前导零do{int x = atoi(str.c_str());if(x % 2 == 0){cout << x << endl;flag = true;break;}}while (next_permutation(str.begin(), str.end()));if(flag == false)cout << -1 << endl;}return 0;
}
体操队形(不懂_dfs+枚举)
体操队形 (nowcoder.com)
#include <iostream>
#include <vector>
using namespace std;int n = 0, res = 0;void dfs(vector<int>& arr, int pos, vector<bool>& vis)
{if(pos == n + 1) // 找到一个合法方案{++res;return;}for(int i = 1; i <= n; ++i){if(vis[i] == true) // 当前i已经放过了,剪枝continue;if(vis[arr[i]] == true) // 当前i的诉求已经放过了,剪枝return;vis[i] = true; // 放上idfs(arr, pos + 1, vis);vis[i] = false; // 回溯}
}int main()
{cin >> n;vector<int> arr(n + 1);vector<bool> vis(n + 1);for(int i = 1; i <= n; ++i){cin >> arr[i];}dfs(arr, 1, vis);cout << res << endl;return 0;
}
NC6二叉树的最大路径和(dfs+树形dp)
二叉树中的最大路径和_牛客题霸_牛客网
- 树形dp:
- a. 左子树收集:以左子树为起点的最大单链和;
- b. 右子树收集:以右子树为起点的最大单链和;
- c. 根节点要做的事情:整合左右子树的信息,得到经过根节点的最大路径和;
- d. 向上返回:以根节点为起点的最大单链和。
原两分钟写的代码:
/*** struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* };*/class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param root TreeNode类 * @return int整型*/int pathSum = 0;int maxPathSum(TreeNode* root) {dfs(root);return pathSum;}void dfs(TreeNode* root){if(root == nullptr)return;pathSum = max(pathSum, pathSum + root->val);dfs(root->left);dfs(root->right);}
};
正解代码:
/*** struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* };*/#include <climits>
class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param root TreeNode类 * @return int整型*/int pathSum = INT_MIN;int maxPathSum(TreeNode* root) {dfs(root);return pathSum;}int dfs(TreeNode* root) // 获取以此结点为根结点的最大单链和{if(root == nullptr)return 0;int left = max(0, dfs(root->left)); // 获取左子树的最大单链和int right = max(0, dfs(root->right)); // 获取右子树的最大单链和pathSum = max(pathSum, root->val + left + right); // 更新经过次结点最大路径和return root->val + max(left, right); // 返回最大单链和}
};
Day29
排序子序列(之前写过的题竟然才过了百分之50)
排序子序列_牛客笔试题_牛客网
之前写的代码:
#include <iostream>
#include <vector>
using namespace std;
int main()
{int n = 0, cnt = 0;cin >> n;vector<int> v(n+1, 0); // 防止数组越界for (int i = 0; i < n; ++i){cin >> v[i];}for (int i = 0; i < n; ++i){if (v[i+1] > v[i]) // 非递减{while(i < n && v[i+1] >= v[i]){++i; // i走到非递减尽头}++cnt;}else if (v[i+1] < v[i]) // 非递增{while(i < n && v[i+1] <= v[i]){++i; // i走到非递增尽头}cnt++;}}cout << cnt;return 0;
}
笔试写的代码:
#include <iostream>
#include <vector>
using namespace std;int main() // 贪心?
{int n = 0;cin >> n;vector<int> arr(n);for(int i = 0; i < n; ++i){cin >> arr[i];}// int res = 1;// int flag = 0;// for(int i = 0; i < n - 1; ++i)// {// if(arr[i + 1] == arr[i])// continue;// if((arr[i + 1] - arr[i]) * flag <= 0) // 异号// ++res;// flag = arr[i + 1] - arr[i];// }// cout << res << endl;// return 0;int res = 1;int flag = arr[1] - arr[0];for(int left = 0, right = 1; right < n; ++right){if((arr[right] - arr[left]) * flag < 0) // 异号{++res;// cout << arr[left] << " " << arr[right] << endl;if(right + 1 < n){flag = arr[right + 1] - arr[right];}left = right;}else++left;}cout << res << endl;return 0;
}
正解代码:
#include <iostream>
#include <vector>
using namespace std;
int main()
{int n = 0, cnt = 0;cin >> n;vector<int> v(n + 1, 0); // 防止数组越界for (int i = 0; i < n; ++i){cin >> v[i];}for(int i = 1; i <= n; ++i) // n是判断最后一个元素单独为一个序列的情况{if(i == n - 1) // 数组不多开一个空间且 i != n的话就这样写{++cnt;break;}if(v[i] > v[i - 1]){while(i < n && v[i] >= v[i - 1]){++i;}++cnt;}else if(v[i] < v[i - 1]) // 注意不能直接写成if{while(i < n && v[i] <= v[i - 1]){++i;}++cnt;}else{while(i < n && v[i] == v[i - 1]){++i;}}}cout << cnt;return 0;
}
消减整数(过百分之0)
消减整数 (nowcoder.com)
原代码:通过百分之0 emmmm
#include <iostream>
using namespace std;int main() // 数学
{int T = 0;cin >> T;while(T--){int h = 0;cin >> h;h--;int res = 1, last = 1;int tmp = h, resTmp = 1;while(h > 0){// cout << last << " " << h << endl;if(h - last * 2 >= 0){h -= last * 2;last *= 2;}else if(h - last >= 0){h -= last;}else // 重新计数{h = tmp - 1;tmp--;res = resTmp + 1;resTmp++;}++res;}cout << res << endl;}return 0;
}
题解代码:
#include <iostream>
using namespace std;int main() // 贪心 + 数学
{int T = 0;cin >> T;while(T--){int h = 0;cin >> h;h--;int res = 1, last = 1;while(h > 0){// cout << last << " " << h << endl;// if(h - last * 2 >= 0)if(h % (last * 2) == 0) // 注意加括号{h -= last * 2;last *= 2;}else{h -= last;}++res;}cout << res << endl;}return 0;
}
NC164最长上升子序列(二)(贪心+二分)
最长上升子序列(二)_牛客题霸_牛客网
原代码:(看了下之前的代码写的,dp写错了,要全初始化为1)
#include <algorithm>
class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** 该数组最长严格上升子序列的长度* @param a int整型vector 给定的数组* @return int整型*/int LIS(vector<int>& a) { // dp n^2, 贪心+二分 nlognif(a.size() == 0)return 0;vector<int> nums;nums.push_back(a[0]);int n = a.size();for(int i = 1; i < n; ++i){if(a[i] > nums.back()){nums.push_back(a[i]);}else // 找到第一个大于的左端点插入?{int left = 0, right = nums.size() - 1;while(left < right){int mid = (left + right) >> 1;if (nums[mid] < a[i])left = mid + 1;elseright = mid;}nums[left] = a[i];// auto pos = upper_bound(a.begin(), a.end(), a[i]);// *pos = a[i];}}return nums.size();// int n = a.size();// vector<int> dp(n + 1);// int res = 1;// for(int i = 1; i <= n; ++i)// {// for(int j = 0; j < i; ++j)// {// if(a[j] < a[i])// dp[i] = max(dp[i], dp[j] + 1);// }// res = max(res, dp[i]);// }// return res;}
};
新代码:
class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** 该数组最长严格上升子序列的长度* @param a int整型vector 给定的数组* @return int整型*/int LIS(vector<int>& a) { // dp n^2, 贪心+二分 nlognif(a.size() == 0)return 0;vector<int> nums;nums.push_back(a[0]);int n = a.size();for(int i = 1; i < n; ++i){if(a[i] > nums.back()){nums.push_back(a[i]);}else // 找到第一个大于的左端点插入?{// int left = 0, right = nums.size() - 1;// while(left < right)// {// int mid = (left + right) >> 1;// if (nums[mid] < a[i])// left = mid + 1;// else// right = mid;// }// nums[left] = a[i];auto pos = lower_bound(nums.begin(), nums.end(), a[i]); // 我趣!!!if(pos != nums.end())*pos = a[i];}}return nums.size();// int n = a.size(), res = 1; // dp解法_超时// vector<int> dp(n, 1); // 注意不能n个0// for(int i = 1; i < n; ++i)// {// for(int j = 0; j < i; ++j)// {// if(a[j] < a[i])// dp[i] = max(dp[i], dp[j] + 1);// }// res = max(res, dp[i]);// }// return res;}
};
Day30
爱吃素(参数也要开long long,过百分之60)
爱吃素 (nowcoder.com)
#include <cmath>
#include <iostream>
using namespace std;bool isPrime(long long x) // 参数也要开long long !!!!!!
{if (x < 2)return false;for (int i = 2; i <= sqrt(x); ++i){if (x % i == 0)return false;}return true;
}int main()
{int t = 0;cin >> t;while (t--){long long a = 0, b = 0;cin >> a >> b;if ((a == 1 && isPrime(b)) || (b == 1 && isPrime(a)))cout << "YES" << endl;elsecout << "NO" << endl;}return 0;
}
相差不超过k的最多数(想到排序没想到滑动窗口,过百分之十)
相差不超过k的最多数_牛客题霸_牛客网
原代码:
#include <algorithm>
#include <climits>
#include <cstdint>
#include <iostream>
#include <vector>
using namespace std;int main() // 01背包?-> n^2 不行, 排序过百分之30,从中间选数?
{int n = 0, k = 0;cin >> n >> k;vector<int> arr(n);for(int i = 0; i < n; ++i){cin >> arr[i];}// sort(arr.begin(), arr.end()); // 从中间选数 过百分之7// int left = 0, right = n - 1;// int i = (right + left) >> 1;// int cnt = 1;// int maxVal = arr[i], minVal = arr[i];// while(i >= 0 && i < arr.size())// {// if(i - 1 >= 0 && i + 1 < arr.size() && // arr[i + 1] - arr[i] > arr[i] - arr[i - 1])// {// arr.erase(arr.begin() + i); // 选arr[i - 1]// --i;// if(i >= 0)// maxVal = max(maxVal, arr[i]), minVal = min(minVal, arr[i]);// }// else// {// arr.erase(arr.begin() + i); // 选arr[i + 1]// ++i;// if(i < arr.size())// maxVal = max(maxVal, arr[i]), minVal = min(minVal, arr[i]);// }// ++cnt;// if(maxVal - minVal > k)// break;// }// cout << cnt << endl;// return 0;sort(arr.begin(), arr.end()); // 过百分之30int left = 0, right = n - 1;while(left < right){// cout << left << " " << right << endl;// cout << arr[left] << " " << arr[right] << endl;if(arr[right] - arr[left] > k){if(arr[right] - arr[right - 1] > arr[left + 1] - arr[left]){--right;}else{++left;}}else{cout << right - left + 1 << endl;return 0;}}return 0;// vector<vector<int>> dp(n + 1, vector<int>(k + 1));// // dp[i][j]表示从1到i个数中选,maxVal - minVal < j 的最大数量// int maxVal = arr[0], minVal = arr[0];// for(int i = 1; i <= n; ++i)// {// for(int j = 0; j <= k; ++j)// {// if(max(maxVal, arr[i]) - min(minVal, arr[i]) < k ) // 选// {// maxVal = max(maxVal, arr[i]);// minVal = min(minVal, arr[i]);// dp[i][j] = max(dp[i][j], dp[i - 1][maxVal - minVal] + 1);// }// else // 不选// {// dp[i][j] = max(dp[i][j], dp[i - 1][j]);// }// }// // cout << dp[i][k] << endl;// }// cout << dp[n][k] + 1 << endl;// return 0;
}
正解代码_排序+滑动窗口
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;int main() // 排序+滑动窗口
{int n = 0, k = 0;cin >> n >> k;vector<int> arr(n);for(int i = 0; i < n; ++i){cin >> arr[i];}sort(arr.begin(), arr.end());int left = 0, right = 0;int res = 1;while(right < n){while(arr[right] - arr[left] > k){++left;}res = max(res, right - left + 1);++right;}cout << res << endl;return 0;
}
最长公共子序列(AC代码背下来了)
最长公共子序列(一)_牛客题霸_牛客网
#include <iostream>
#include <vector>
using namespace std;
int main()
{int n = 0, m = 0;string str1, str2;cin >> n >> m >> str1 >> str2;;vector<vector<int>> dp(n + 1, vector<int>(m + 1));str1 = " " + str1, str2 = " " + str2;for (int i = 1; i <= n; ++i){for (int j = 1; j <= m; ++j){if (str1[i] == str2[j]){// dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1);dp[i][j] = dp[i - 1][j - 1] + 1;}else{dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);}}}cout << dp[n][m];return 0;
}
Day31
小红的口罩(简单堆模拟)
#include <functional>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;int main() // Day31_1,用堆模拟
{int n = 0, k = 0;cin >> n >> k;vector<int> arr(n);priority_queue<int, vector<int>, greater<int>> heap;for(int i = 0; i < n; ++i){cin >> arr[i];heap.push(arr[i]);}int sum = 0, res = 0;while(heap.size() && sum + heap.top() <= k){int x = heap.top();heap.pop();sum += x;heap.push(x * 2);++res;}cout << res << endl;return 0;
}
春游(贪心+数学分情况讨论,7.5/30)
春游
#include <iostream>
using namespace std;#define int long longsigned main() // Day31_2_简单模拟+贪心
{ // 想的思路全是if else 不想写了,三条二人船和两条三人船的钱比int t = 0;cin >> t;while(t--){int n = 0, a = 0, b = 0;cin >> n >> a >> b;int sum = 0;if(b * 2 <= a * 3)sum = n / 3 * b;else if(n == 3 && a * 2 < b)sum = a * 2;else{sum = n / 2 * a;if(n % 2 != 0)sum += a;}cout << sum << endl;}return 0;
}
正解代码
#include <iostream>
using namespace std;
#define int long longint t;
int n, a, b;int fun()
{if(n <= 2)return min(a, b);int ret = 0;if(a * 3 < b * 2) // 尽可能的选择双⼈船{ret += n / 2 * a;n %= 2;if(n)ret += min(min(a, b), b - a);}else // 尽可能的选择三⼈船{ret += n / 3 * b;n %= 3;if(n == 1)ret += min(min(a, b), 2 * a - b);if(n == 2)ret += min(min(a, b), 3 * a - b);}return ret;
}signed main()
{cin >> t;while(t--){cin >> n >> a >> b;cout << fun() << endl;}return 0;
}
DP59数位染色(01背包)
数位染色_牛客题霸_牛客网
#include <iostream>
#include <vector>
using namespace std;int main() // Day31_3_数组中分开两部分元素,判断能否分为两部分的和相等
{ // 选和不选,01背包?string str;cin >> str;str = ' ' + str;int n = str.size() - 1, sum = 0;for(int i = 1; i <= n; ++i){sum += str[i] - '0';}if(sum % 2 == 1) // 是奇数{cout << "No" << endl;return 0;}// // 选一些数,使其等于sum / 2;// sum /= 2;// vector<int> dp(sum + 1); // 滚动数组优化// // dp[i][j] 表示,从0选到i,能否凑成总和为sum// for(int i = 1; i <= n; ++i)// {// for(int j = sum; j >= 0; --j)// {// // dp[i][j] = dp[i - 1][j]; // 不选// int val = str[i] - '0';// if(j >= val)// dp[j] = max(dp[j], dp[j - val] + val); // 选// // cout << dp[i][j] << endl;// }// }// if(dp[sum] == sum)// cout << "Yes" << endl;// else// cout << "No" << endl;// // 选一些数,使其等于sum / 2;// sum /= 2;// vector<vector<int>> dp(n + 1, vector<int>(sum + 1));// // dp[i][j] 表示,从0选到i,总和不超过j的数的总和// for(int i = 1; i <= n; ++i)// {// for(int j = 1; j <= sum; ++j)// {// dp[i][j] = dp[i - 1][j]; // 不选// int val = str[i] - '0';// if(j >= val)// dp[i][j] = max(dp[i][j], dp[i - 1][j - val] + val); // 选// // cout << dp[i][j] << endl;// }// }// if(dp[n][sum] == sum)// cout << "Yes" << endl;// else// cout << "No" << endl;// 选一些数,使其等于sum / 2; // bool 类型 滚动数组优化sum /= 2;vector<bool> dp(sum + 1);dp[0] = true; // 注意初始化,不选就为true// dp[i][j] 表示,从0选到i,总和能否凑成jfor(int i = 1; i <= n; ++i){int val = str[i] - '0';for(int j = sum; j >= val; --j){dp[j] = dp[j] || dp[j - val]; // 选}}if(dp[sum])cout << "Yes" << endl;elsecout << "No" << endl;// // 选一些数,使其等于sum / 2; // bool 类型// sum /= 2;// vector<vector<bool>> dp(n + 1, vector<bool>(sum + 1, false));// dp[0][0] = true; // 注意初始化,不选就为true// // dp[i][j] 表示,从0选到i,总和能否凑成j// for(int i = 1; i <= n; ++i)// {// for(int j = 1; j <= sum; ++j)// {// dp[i][j] = dp[i - 1][j]; // 不选// int val = str[i] - '0';// if(j >= val)// dp[i][j] = dp[i][j] || dp[i - 1][j - val]; // 选// // cout << dp[i][j] << endl;// }// }// if(dp[n][sum])// cout << "Yes" << endl;// else// cout << "No" << endl;return 0;
}
Day32
BC157素数回文(AC)
素数回文_牛客题霸_牛客网
#include <cmath>
#include <cstdlib>
#include <iostream>
using namespace std;bool isPrime(long long n)
{if(n < 2)return false;for(int i = 2; i <= sqrt(n); ++i){if(n % i == 0)return false;}return true;
}int main()
{string str;cin >> str;string tmp = str;for(int i = str.size() - 2; i >= 0; --i){tmp += str[i];}long long n = atoll(tmp.c_str()); // to long long!!!// cout << n << " ";if(isPrime(n))cout << "prime" << endl;elsecout << "noprime" << endl;return 0;
}
AB31活动安排(15/30,少写一行代码)
活动安排_牛客题霸_牛客网
#include <asm-generic/errno.h>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;#define int long long
signed main() // 背包?// 按照a和b排序??
{int n = 0;cin >> n;vector<vector<int>> arr(n, vector<int>(2));int maxTime = 0;for(int i = 0; i < n; ++i){cin >> arr[i][0] >> arr[i][1];maxTime += arr[i][1];}auto cmp = [=](vector<int> arr1, vector<int> arr2){if(arr1[0] < arr2[0])return true;else if(arr1[0] == arr2[0] && arr1[1] < arr2[1])return true;return false;};// sort(arr.begin(), arr.end(), cmp);sort(arr.begin(), arr.end()); // 不用自己写排序?确实,脑子瓦特了// for(int i = 0; i < n; ++i)// {// cout << arr[i][0] << " " << arr[i][1] << endl;// }int res = 1;int last = arr[0][1];for(int i = 1; i < n; ++i){if(arr[i][0] >= last) // 没有重叠{++res;last = arr[i][1];}else // 有重叠 // 笔试时少了这一句!!!!!!{last = min(last, arr[i][1]);}}cout << res << endl;// sort(arr.begin(), arr.end());// vector<vector<int>> dp(n + 1, vector<int>(maxTime));// // dp[i][j] 表示从1到i中选,活动时间不超过j的活动数?// int res = 0;// for(int i = 2; i <= n; ++i)// {// for(int j = 0; j <= maxTime; ++j)// {// dp[i][j] = dp[i - 1][j]; // 不选// if(j >= arr[i][1] && arr[i][0] >= arr[i - 1][1])// {// dp[i][j] = max(dp[i][j], dp[i][j - arr[i][1]] + 1); // 选// }// res = max(res, dp[i][j]);// }// }// // cout << res << endl;// cout << 2 << endl;return 0;
}
WY6合唱团(4/40,最大乘积dp,忘了)
原代码:(k和d的输入都错了)
#include <iostream>
#include <queue> // 里面有vector
using namespace std;int main() // 打家劫舍dp?
{int n = 0, k = 0, d = 0;cin >> n >> k >> d;vector<int> arr(n);priority_queue<pair<int, int>> heap; // 数和下标for(int i = 0; i < n; ++i){cin >> arr[i]; // 还有负值heap.push({arr[i], i});}long long res = 1;vector<int> arrb;while(k--){auto[a, b] = heap.top();heap.pop();bool flag = true;for(int i = 0; i < arrb.size(); ++i){if(abs(arrb[i] - b) >= k){flag = false;break;}}if(flag)res *= a;}cout << res << endl;return 0;
}
正解代码:
#include <iostream>
#include <queue> // 里面有vector
#include <vector>
using namespace std;#define int long long
const int INF = 0x3f3f3f3f3f3f3f3f;signed main() // 打家劫舍dp?
{int n = 0, k = 0, d = 0;cin >> n;vector<int> arr(n + 1);for(int i = 1; i <= n; ++i){cin >> arr[i]; // 还有负值}cin >> k >> d;vector<vector<int>> f(n + 1, vector<int>(k + 1, -INF));vector<vector<int>> g(n + 1, vector<int>(k + 1, INF));// f[i][j]/g[i][j]表示从1到i挑选j个人第i个人必选的最大/小乘积for(int i = 1; i <= n; ++i){f[i][1] = g[i][1] = arr[i]; // 初始化for(int j = 2; j <= min(i, k); ++j){// i - prev <= d 所以 prev >= i - dfor(int prev = max(i - d, j - 1); prev <= i - 1; ++prev) // prev代表前面挑选的最后一个位置{f[i][j] = max(f[i][j], max(f[prev][j - 1] * arr[i], g[prev][j - 1] * arr[i]));g[i][j] = min(g[i][j], min(f[prev][j - 1] * arr[i], g[prev][j - 1] * arr[i]));}}}int res = 0;for(int i = k; i <= n; ++i){res = max(res, f[i][k]);}cout << res << endl;return 0;
}
Day33(全AC)
DP3跳台阶扩展问题(dp或找规律)
#include <iostream>
#include <vector>
using namespace std;int main() // Day33_1_dp或找规律
{int sum = 0, n = 0;cin >> n;// n = 20; // 打表vector<int> dp(n + 1, 1);// dp[i]表示跳到第i级台阶有多少种跳法for(int i = 2; i <= n; ++i){for(int j = 1; j < i; ++j){dp[i] += dp[j]; // !!!!!!!!!}}// for(int i = 1; i < n; ++i) // 打表或者找规律:2^(n - 1)// {// cout << dp[i] << endl;// }cout << dp[n];return 0;
}/*
O(1)时间:
1
2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
131072
262144
524288
*/
找规律:
#include <iostream>
#include <vector>
using namespace std;int main() // Day33_1_dp或找规律
{int n = 0;cin >> n;cout << (1 << (n - 1));return 0;
}
NC402包含不超过两种字符的最长子串(滑动窗口)
#include <climits>
#include <iostream>
#include <unordered_map>
using namespace std;int main() // Day33_2_滑动窗口
{string str;cin >> str;unordered_map<char, int> hash;int n = str.size();int res = min(2, n);for(int left = 0, right = 0; right < n; ++right){hash[str[right] - '0']++;while(left < n && hash.size() > 2){hash[str[left] - '0']--;if(hash[str[left] - '0'] == 0){hash.erase(str[left] - '0');}left++;}res = max(res, right - left + 1);}cout << res;return 0;
}
MGJ14字符串的排列(dfs或next_permutation)
原本的next_permutation代码+dfs代码:
class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param str string字符串 * @return string字符串vector*/vector<string> ret;string path;bool vis[11] = { false };string s;int n;vector<string> Permutation(string str) { // Day33_3_全排列// vector<string> ret;// sort(str.begin(), str.end());// do// {// ret.push_back(str);// }while (next_permutation(str.begin(), str.end()));// return ret;sort(str.begin(), str.end());s = str;n = s.size();dfs(0);return ret;}void dfs(int pos){if(pos == n){ret.push_back(path);return;}for(int i = 0; i < n; ++i){if(vis[i] || (i > 0 && s[i] == s[i - 1] && !vis[i - 1]))continue;path += s[i];vis[i] = true;dfs(pos + 1);vis[i] = false;path.pop_back();}}
};
Day34(就AC第一道)
BC76[NOIP2008]ISBN号码(简单模拟)
[NOIP2008]ISBN号码_牛客题霸_牛客网
#include <iostream>
using namespace std;int main() // Day34_1_简单模拟
{string tmp, str;cin >> tmp;int n = tmp.size();for(int i = 0; i < n; ++i){if(tmp[i] != '-')str += tmp[i];}long long x = 0;// cout << str << endl;for(int i = 0; i < str.size() - 1; ++i){x += ((str[i] - '0') * (i + 1));// cout << x << " "; }// cout << endl;int val = x % 11;char ch;if(val == 10)ch = 'X';elsech = val + '0';if(tmp[n - 1] == ch)cout << "Right" << endl;else{tmp[n - 1] = ch;cout << tmp << endl;}// cout << x << " " << " " << val << " " << ch << endl;return 0;
}
kotori和迷宫(BFS+dist数组)
kotori和迷宫
原代码:(没想到dist数组,且是push,不是递归!!!脑子瓦特了,bfs用队列就行,不用堆)
#include <climits>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;int m = 0, n = 0;
int cnt = 0, step = INT_MAX, level = 0; // 出口数量,和最近出口距离,bfs层数
int dx[4] = {0, 0, -1, 1};
int dy[4] = {1, -1, 0, 0};
bool vis[31][31];void bfs(vector<vector<char>>& arr, int sr, int sc)
{vis[sr][sc] = true;if(arr[sr][sc] == 'e'){// cout << sr << " " << sc << endl;++cnt;step = min(step, level);// cout << "level " << level << endl;return;}// cout << cnt << endl;priority_queue<pair<int, int>> q;q.push({sr, sc});while(q.size()){auto [a, b] = q.top();q.pop();level++;for(int i = 0; i < 4; ++i){int x = a + dx[i], y = b + dy[i];if(x >= 1 && x <= m && y >= 1 && y <= n && !vis[x][y] && arr[x][y] != '*'){bfs(arr, x, y);}}}
}int main() // Day34_2_bfs
{cin >> m >> n;vector<vector<char>> arr(m + 1, vector<char>(n + 1));int sr = 0, sc = 0;for(int i = 1; i <= m; ++i){for(int j = 1; j <= n; ++j){cin >> arr[i][j];if(arr[i][j] == 'k')sr = i, sc = j;}}bfs(arr, sr, sc);if(cnt == 0)cout << -1 << endl;elsecout << cnt << " " << step - 2 << endl;return 0;
}/*
6 8
e . * . * e . *
. * * . * . * e
. . * k * * . .
* * * . * . e *
. * * . * . * *
* . . . . . . e
*/
正解代码:
#include <climits>
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;int m = 0, n = 0;
int dx[4] = {0, 0, -1, 1};
int dy[4] = {1, -1, 0, 0};
int dist[31][31];void bfs(vector<vector<char>>& arr, int sr, int sc)
{queue<pair<int, int>> q;q.push({sr, sc});while(q.size()){auto [a, b] = q.front();q.pop();for(int i = 0; i < 4; ++i){int x = a + dx[i], y = b + dy[i];if(x >= 1 && x <= m && y >= 1 && y <= n && dist[x][y] == -1 && arr[x][y] != '*'){dist[x][y] = dist[a][b] + 1;if(arr[x][y] != 'e')q.push({x, y});}}}
}int main() // Day34_2_bfs
{memset(dist, -1, sizeof(dist));cin >> m >> n;vector<vector<char>> arr(m + 1, vector<char>(n + 1));int sr = 0, sc = 0;for(int i = 1; i <= m; ++i){for(int j = 1; j <= n; ++j){cin >> arr[i][j];if(arr[i][j] == 'k')sr = i, sc = j;}}dist[sr][sc] = 0;bfs(arr, sr, sc);int cnt = 0, minStep = INT_MAX;for(int i = 1; i <= m; ++i){for(int j = 1; j <= n; ++j){if(arr[i][j] == 'e' && dist[i][j] != -1){++cnt;minStep = min(minStep, dist[i][j]);}}}if(cnt == 0)cout << -1 << endl;elsecout << cnt << " " << minStep << endl;return 0;
}/*
6 8
e . * . * e . *
. * * . * . * e
. . * k * * . .
* * * . * . e *
. * * . * . * *
* . . . . . . e
*/
NC138矩阵最长递增路径(记忆化搜索)
矩阵最长递增路径_牛客题霸_牛客网
class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** 递增路径的最大长度* @param matrix int整型vector<vector<>> 描述矩阵的每个数* @return int整型*/int m = 0, n = 0;int step = INT_MIN, level = 0; // 距离,bfs层数int dx[4] = {0, 0, -1, 1};int dy[4] = {1, -1, 0, 0};bool vis[1001][1001];int dfsLevel = 1, ret = 0;int solve(vector<vector<int> >& matrix) { // dfs?m = matrix.size(), n = matrix[0].size();dfs(matrix, 0, 0);vis[0][0] = true;return ret;}void dfs(vector<vector<int>>& arr, int sr, int sc){ret = max(ret, dfsLevel);// cout << sr << " " << sc << " " << arr[sr][sc] << " " << dfsLevel << endl;for(int i = 0; i < 4; ++i){int x = sr + dx[i], y = sc + dy[i];if(x >= 0 && x < m && y >= 0 && y < n && !vis[x][y] && arr[x][y] >= arr[sr][sc]){vis[x][y] = true;++dfsLevel;dfs(arr, x, y);vis[x][y] = false;--dfsLevel;}}}
};
正解代码:
class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** 递增路径的最大长度* @param matrix int整型vector<vector<>> 描述矩阵的每个数* @return int整型*/int m = 0, n = 0;int dx[4] = {0, 0, -1, 1};int dy[4] = {1, -1, 0, 0};int memo[1007][1007];int solve(vector<vector<int> >& matrix) { // dfs?memset(memo, -1, sizeof(memo));m = matrix.size(), n = matrix[0].size();// dfs(matrix, 0, 0);int ret = 0;for(int i = 0; i < m; ++i) // 可以以任何位置为起点{for(int j = 0; j < n; ++j){ret = max(ret, dfs(matrix, i, j));}}return ret;}int dfs(vector<vector<int>>& arr, int sr, int sc){if(memo[sr][sc] != -1)return memo[sr][sc];int len = 1;// cout << sr << " " << sc << " " << arr[sr][sc] << " " << dfsLevel << endl;for(int i = 0; i < 4; ++i){int x = sr + dx[i], y = sc + dy[i];if(x >= 0 && x < m && y >= 0 && y < n && arr[x][y] > arr[sr][sc]) // 严格递增{len = max(len, 1 + dfs(arr, x, y));}}memo[sr][sc] = len;return len;}
};
Day35(全AC但后两题有点呆)
MT8奇数位丢弃(模拟或找规律?)
奇数位丢弃_牛客题霸_牛客网
#include <iostream>
#include <vector>
using namespace std;int main() // Day35_1_简单模拟或找规律?
{int n = 1;// while(n++ <= 1000)while(cin >> n){vector<int> arr;for(int i = 1; i <= n; i += 2){ arr.push_back(i);}int j = 0;while(arr.size() != 1){if(j < arr.size())arr.erase(arr.begin() + j);j += 1; // 原来+=2的,但删去一个了if(j > arr.size())j = 0;}cout << arr[0] << endl;// cout << n << " " << arr[0] << endl}return 0;
}
解法二:
#include <iostream>
#include <vector>
using namespace std;int main() // Day35_1_简单模拟或找规律?
{int n = 1;while(cin >> n){int ret = 1;while(ret - 1 <= n){ret *= 2;}cout << ret / 2 - 1;}return 0;
}
OR64求和(dfs爆搜)
求和__牛客网
原呆子代码:
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;set<set<int>> res;
set<int> path;
int sum = 0;
int n = 0, m = 0;void dfs(int i)
{// cout << "i " << i << " sum " << sum << endl;if(sum >= m){if(sum == m){res.insert(path);}return;}for(int j = i; j <= n; ++j){auto pos = path.insert(j); // 选if(pos.second != false)sum += j;dfs(i + 1);auto pos2 = path.erase(j); // 不选,回溯if(pos2 != false)sum -= j;}
}// 1 2 3 4 5
int main() // Day35_2_01背包 ??? dfs爆搜?
{cin >> n >> m;for(int i = 1; i <= min(n, m); ++i){dfs(i); // 从i开始选}for(auto& arr : res){for(auto& e : arr){cout << e << " ";}cout << endl;}// int cnt = 0; // emmmmmmmmmmmmmmmmmmmmmmmmm// for(auto& arr : res)// {// int cnt2 = 0;// for(auto& e : arr)// {// cout << e;// ++cnt2;// if(cnt2 != arr.size())// cout << " ";// }// ++cnt;// if(cnt != res.size())// cout << "<br/>";// }// vector<vector<vector<int>>> dp(n + 1, vector<vector<int>>(m + 1));// dp[i][j] 表示从第1个到第i个数中选出和等于m的数存到第三维的数组里// vector<vector<int>> dp(n + 1, vector<int>(m + 1));// // dp[i][j] 表示从第1个到第i个数中选出和等于m的数存到arr数组里// for(int i = 1; i <= n; ++i)// {// vector<int> arr;// for(int j = 1; j <= m; ++j)// {// dp[i][j] = dp[i - 1][j]; // 不选// if(j >= i && dp[i][j] < dp[i][j - i] + i)// {// dp[i][j] = max(dp[i][j], dp[i][j - i] + i);// arr.push_back(i); // 选// }// if(j == m)// {// for(auto& e : arr)// {// cout << e << " ";// }// cout << endl;// }// }// }return 0;
}
题解代码:
#include <iostream>
#include <vector>
using namespace std;vector<vector<int>> res;
vector<int> path;
int sum = 0;
int n = 0, m = 0;
bool vis[11];void dfs(int i) // 考虑i选还是不选
{// cout << "i " << i << " sum " << sum << endl;if(sum >= m || i > n){if(sum == m)res.push_back(path);return;}sum += i; // 选path.push_back(i);vis[i] = true; dfs(i + 1);sum -= i; // 回溯path.pop_back();vis[i] = false;dfs(i + 1); // 不选!!!!!!!!!
}// 1 2 3 4 5
int main() // Day35_2_dfs爆搜
{cin >> n >> m;dfs(1);for(auto& arr : res){for(auto& e : arr){cout << e << " ";}cout << endl;}return 0;
}
另一份代码:(直接在dfs里用vis数组输出)
#include <iostream>
#include <vector>
using namespace std;int sum = 0;
int n = 0, m = 0;
bool vis[11];void dfs(int i) // 考虑i选还是不选
{if(sum >= m || i > n){if(sum == m){for(int i = 1; i <= n; ++i){if(vis[i])cout << i << " ";}cout << endl;}return;}sum += i; // 选vis[i] = true; dfs(i + 1);sum -= i; // 回溯vis[i] = false;dfs(i + 1); // 不选!!!!!!!!!
}int main() // Day35_2_dfs爆搜
{cin >> n >> m;dfs(1);return 0;
}
HJ52计算字符串的编辑距离
计算字符串的编辑距离_牛客题霸_牛客网
#include <climits>
#include <iostream>
#include <vector>
using namespace std;int main() // Day35_3_两个数组dp_上一次笔试强训写过
{string str1, str2;cin >> str1 >> str2;int n1 = str1.size(), n2 = str2.size();// if(n1 == 0 || n2 == 0)// {// cout << max(n1, n2) << endl;// return 0;// }vector<vector<int>> dp(n1 + 1, vector<int>(n2 + 1));for(int i = 1; i <= n1; ++i){dp[i][0] = i;}for(int j = 1; j <= n2; ++j){dp[0][j] = j;}for(int i = 1; i <= n1; ++i){for(int j = 1; j <= n2; ++j){if(str1[i - 1] == str2[j - 1]) // 相等,继承i-1,j-1的编辑距离不用 + 1dp[i][j] = dp[i - 1][j - 1];elsedp[i][j] = min(dp[i - 1][j - 1] + 1, min(dp[i][j - 1], dp[i - 1][j]) + 1);}}cout << dp[n1][n2] << endl;return 0;
}
Day36(全AC,看了第二题模板)
HJ9提取不重复的整数(简单模拟)
提取不重复的整数_牛客题霸_牛客网
#include <iostream>
#include <vector>
using namespace std;int main() // Day36_1_简单模拟
{vector<bool> arr(10, false);string str, ret;cin >> str;for(int i = str.size() - 1; i >= 0; --i){if(arr[str[i] - '0'] == false){ret += str[i];arr[str[i] - '0'] = true;}}cout << atoi(ret.c_str()) << endl;return 0;
}
AB32 【模板】哈夫曼编码
【模板】哈夫曼编码_牛客题霸_牛客网
题解和代码:
哈夫曼编码(Huffman Coding)是一种被广泛使用的可变长度编码方式,由David A. Huffman在1952年提出。它主要用于数据压缩领域,特别是当数据的某些部分比其他部分更频繁地出现时。哈夫曼编码基于一种贪心算法来构建一棵最优二叉树(通常称为哈夫曼树),用于对数据进行编码。
以下是哈夫曼编码的基本概念和工作原理:
频率统计:首先,统计输入数据中每个符号(如字符、单词或任何其他可识别的单元)出现的频率。
构建哈夫曼树:使用这些频率作为权重,通过贪心算法构建一棵哈夫曼树。在构建过程中,权重最小的两个节点被合并为一个新的内部节点,该内部节点的权重为两个子节点权重之和。这个过程一直重复,直到只剩下一个节点(即树的根)。
生成编码:在哈夫曼树中,从根节点到每个叶子节点的路径(通过左子节点或右子节点)被转换为一串二进制数,这就是该叶子节点对应符号的哈夫曼编码。由于树的构建是基于权重的,因此更常见的符号(即权重更大的符号)通常具有较短的编码,而不常见的符号则具有较长的编码。
编码数据:使用生成的哈夫曼编码替换输入数据中的每个符号。
解码数据:由于哈夫曼编码是前缀码(即任何符号的编码都不是另一个符号编码的前缀),因此解码过程相对简单。只需按照编码的二进制串在哈夫曼树中查找即可。
哈夫曼编码是一种非常有效的数据压缩方法,特别适用于那些符号频率分布不均匀的数据。然而,由于需要构建哈夫曼树和生成编码,因此哈夫曼编码的压缩和解压过程相对较慢。此外,哈夫曼编码生成的压缩数据是自适应的,即不同的数据可能生成不同的哈夫曼树和编码,因此通常需要在压缩数据中附带哈夫曼树的信息以便于解压。
计算结果:
#include <functional>
#include <iostream>
#include <queue>
using namespace std;
#define int long longsigned main() // Day36_2_哈夫曼编码模板
{int n = 0, x = 0, ret = 0;cin >> n;priority_queue<int ,vector<int>, greater<int>> heap;while(n--){cin >> x;heap.push(x);}while(heap.size() != 1){long long x1 = heap.top();heap.pop();long long x2 = heap.top();heap.pop();heap.push(x1 + x2);ret += x1 + x2;}cout << ret << endl;return 0;
}
DP36 abb(dp或暴力)
暴力代码:(也就时间复杂度也就O(26N))
#include <iostream>
#include <vector>
using namespace std;int main() // Day36_3_滑动窗口?不是
{int n = 0;string str;cin >> n >> str;vector<int> arr(26);for(int i = 0; i < n; ++i){arr[str[i] - 'a']++;}// for(int j = 0; j < 26; ++j)// {// cout << arr[j] << " ";// }long long ret = 0;for(int i = 0; i < n; ++i) // 计算str[i]右边有多少个其它字符{for(int j = 0; j < 26; ++j){if(str[i] - 'a' != j && arr[j] >= 2){// int cnt = 0; // 用下面的的等差数列求和公式求// for(int k = arr[j] - 1; k >= 1; --k)// {// cnt += k;// }// ret += cnt;// 等差数列求和公式:n * (a1 + an) / 2ret += (arr[j] - 1) * (1 + arr[j] - 1) / 2; // 求组合数C n 2?}}// cout << ret << " " << str[i] << " " << arr[str[i] - 'a'] << endl; // debugarr[str[i] - 'a']--;}cout << ret;return 0;
}
/*
3个c 3, 4个c 6
7
abcbccc // 6个acc n个c (n-1)!, 3+2+1
8
abcbcccc // 24个acc 5个c (n-1)!, 4+3+2
*/
题解dp代码:
#include <iostream>
#include <vector>
using namespace std;int main() // Day36_3_滑动窗口?不是
{int n = 0;string str;cin >> n >> str;vector<int> arr(26);for(int i = 0; i < n; ++i){arr[str[i] - 'a']++;}// for(int j = 0; j < 26; ++j)// {// cout << arr[j] << " ";// }long long ret = 0;for(int i = 0; i < n; ++i) // 计算str[i]右边有多少个其它字符{for(int j = 0; j < 26; ++j){if(str[i] - 'a' != j && arr[j] >= 2){int cnt = 0;for(int k = arr[j] - 1; k >= 1; --k){cnt += k;}ret += cnt;}}// cout << ret << " " << str[i] << " " << arr[str[i] - 'a'] << endl; // debugarr[str[i] - 'a']--;}cout << ret;return 0;
}
/*
3个c 3, 4个c 6
7
abcbccc // 6个acc n个c (n-1)!, 3+2+1
8
abcbcccc // 24个acc 5个c (n-1)!, 4+3+2
*/
Day_37_就第一题有点用例没过
NC114旋转字符串(这么简单竟然没AC)
旋转字符串_牛客题霸_牛客网
class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** 旋转字符串* @param A string字符串 * @param B string字符串 * @return bool布尔型*/bool solve(string A, string B) {// write code here}
};
解法1及代码:
按照题目的要求模拟,每次旋转一下A字符串,看看是否和B字符串相同。
class Solution {
public:bool solve(string A, string B) {for(int i = 1; i <= A.size(); ++i){string tmp1 = A.substr(0, i);string tmp2 = A.substr(i, A.size());if(tmp2 + tmp1 == B)return true;}return false;}
};
解法2及代码:
需要找到字符串旋转之后能匹配所满足的性质。 如果 A 字符串能够旋转之后得到 B 字符串的话,在 A 字符串倍增之后的新串中,一定是可以找到 B 字符串的。 因此仅需让 A 字符串倍增,然后查找 B 字符串即可。
class Solution {
public:bool solve(string A, string B) {if(A.size() != B.size())return false;return (A + A).find(B) != -1;}
};
原傻子代码:
#include <algorithm>
class Solution {
public:bool solve(string A, string B) { // Day37_1_模拟?int n1 = A.size(), n2 = B.size();if(n1 != n2)return false;for(int i = 1; i <= n1; ++i){// cout << B.substr(0, i) << endl;int pos = A.find(B.substr(0, i));if(pos == string::npos)continue;// cout << pos << endl;// cout << i << " " << n1 << endl;if(pos == 0 || pos + i == n1) // 如果能分成两段{return true;}// string tmp = B.substr(0, i);// for(int i = 1; i <= n1; ++i) // 比较前一段// {// if(tmp == A.substr(0, i))// return true;// }// for(int i = 0; i < n1; ++i) // 比较后一段// {// if(tmp == A.substr(i))// return true;// }}return false;// sort(A.begin(), A.end());// do // next_permutation过75%,但是是错的,不是超时,因为只能移动两个// {// if(A == B)// return true;// }while (next_permutation(A.begin(), A.end()));// return false;}
};
面向答案编程改了return的条件就AC了:
#include <algorithm>
class Solution {
public:bool solve(string A, string B) { // Day37_1_模拟?int n1 = A.size(), n2 = B.size();if(n1 != n2)return false;for(int i = 1; i <= n1; ++i){// cout << B.substr(0, i) << endl;int pos = A.find(B.substr(0, i));if(pos == string::npos)continue;// cout << pos << endl;// cout << i << " " << n1 << endl;if(pos == 0 || (i != 1 && pos + i == n1)) // 如果能分成两段{return true;}// string tmp = B.substr(0, i);// for(int i = 1; i <= n1; ++i) // 比较前一段// {// if(tmp == A.substr(0, i))// return true;// }// for(int i = 0; i < n1; ++i) // 比较后一段// {// if(tmp == A.substr(i))// return true;// }}return false;// sort(A.begin(), A.end());// do // next_permutation过75%,但是是错的,不是超时,因为只能移动两个// {// if(A == B)// return true;// }while (next_permutation(A.begin(), A.end()));// return false;}
};
NC51合并k个已排序的链表(取巧了)
原代码:
class Solution {
public:ListNode* mergeKLists(vector<ListNode*>& lists) { // Day37_2_链表vector<int> arr;for(auto& e : lists){ListNode* cur = e;while(cur != nullptr){arr.push_back(cur->val);cur = cur->next;}}sort(arr.begin(), arr.end());ListNode* tail = new ListNode(0);ListNode* ret = tail;for(auto& e : arr){ListNode* tmp = new ListNode(e); // 要在堆开空间tail->next = tmp;tail = tail->next;}return ret->next;}
};
用堆模拟:
class Solution {struct cmp{bool operator()(ListNode* l1, ListNode* l2){return l1->val > l2->val;}};public:ListNode* mergeKLists(vector<ListNode*>& lists) {priority_queue<ListNode*, vector<ListNode*>, cmp> heap; // ⼩根堆for (auto head : lists){if (head != nullptr)heap.push(head);}ListNode* ret = new ListNode(0);ListNode* prev = ret;while (heap.size()){ListNode* t = heap.top();heap.pop();prev = prev->next = t;if (t->next != nullptr){heap.push(t->next);}}ListNode* tmp = ret->next;free(ret);return tmp;}
};
DP18滑雪(用dfs没改记忆化搜索也AC了)
滑雪_牛客题霸_牛客网
#include <iostream>
#include <vector>
using namespace std;
int n = 0, m = 0, len = 1, resLen = 0;
vector<int> path;
bool vis[101][101];
int dx[4] = {0, 0, -1, 1};
int dy[4] = {1, -1, 0, 0};void dfs(vector<vector<int>>& arr, int sr, int sc)
{resLen = max(len, resLen);for(int i = 0; i < 4; ++i){int x = sr + dx[i], y = sc + dy[i];if(x >= 0 && x < n && y >= 0 && y < m&& !vis[x][y] && arr[x][y] > arr[sr][sc]){path.push_back(arr[x][y]);++len;dfs(arr, x, y);path.pop_back();--len;}}
}int main() // Day37_3_dfs_一遍过,这么强的吗
{cin >> n >> m;vector<vector<int>> arr(n, vector<int>(m));for(int i = 0; i < n; ++i){for(int j = 0; j < m; ++j){cin >> arr[i][j];}}for(int i = 0; i < n; ++i){for(int j = 0; j < m; ++j){dfs(arr, i, j);}}cout << resLen << endl;return 0;
}
记忆化搜索代码:
#include <iostream>
#include <vector>
using namespace std;
int n = 0, m = 0;
bool vis[101][101];
int memo[101][101];
int dx[4] = {0, 0, -1, 1};
int dy[4] = {1, -1, 0, 0};int dfs(vector<vector<int>>& arr, int sr, int sc)
{if(memo[sr][sc] != 0) // 记忆化搜索return memo[sr][sc];int len = 1;for(int i = 0; i < 4; ++i){int x = sr + dx[i], y = sc + dy[i];if(x >= 0 && x < n && y >= 0 && y < m&& !vis[x][y] && arr[x][y] > arr[sr][sc]){len = max(len, 1 + dfs(arr, x, y));}}memo[sr][sc] = len;return len;
}// int n = 0, m = 0, len = 1, resLen = 0;
// vector<int> path;
// bool vis[101][101];
// void dfs(vector<vector<int>>& arr, int sr, int sc)
// {
// resLen = max(len, resLen);
// for(int i = 0; i < 4; ++i)
// {
// int x = sr + dx[i], y = sc + dy[i];
// if(x >= 0 && x < n && y >= 0 && y < m
// && !vis[x][y] && arr[x][y] > arr[sr][sc])
// {
// path.push_back(arr[x][y]);
// ++len;
// dfs(arr, x, y);
// path.pop_back();
// --len;
// }
// }
// }int main() // Day37_3_dfs_一遍过,这么强的吗
{cin >> n >> m;vector<vector<int>> arr(n, vector<int>(m));for(int i = 0; i < n; ++i){for(int j = 0; j < m; ++j){cin >> arr[i][j];}}int resLen = 0;for(int i = 0; i < n; ++i){for(int j = 0; j < m; ++j){resLen = max(resLen, dfs(arr, i, j));}}cout << resLen << endl;return 0;
}
Day38(全都不会)
天使果冻(dp找第二大)
天使果冻
原代码:
#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
//int main()
//{
// int n = 0;
// cin >> n;
// vector<int> arr(n);
// for (int i = 0; i < n; ++i)
// {
// cin >> arr[i];
// }
// int q = 0;
// cin >> q;
// while (q--)
// {
// int cnt = 0;
// cin >> cnt;
// vector<int> tmpArr(arr.begin(), arr.begin() + cnt);
// sort(tmpArr.begin(), tmpArr.end()); // 这个时间复杂度还不行。滑动窗口?
// cout << tmpArr[cnt - 2] << endl;
// }
// return 0;
//}
//int main() // 维护第二大的数,答案错误
//{
// int n = 0;
// cin >> n;
// vector<int> arr(n);
// for (int i = 0; i < n; ++i)
// {
// cin >> arr[i];
// }
// int q = 0;
// cin >> q;
// while (q--)
// {
// int cnt = 0;
// cin >> cnt;
// int maxVal = arr[0], maxIndex = 0, res = arr[0];
// for (int i = 1; i < cnt; ++i)
// {
// if (arr[i] > maxVal)
// {
// res = maxVal;
// maxVal = arr[i];
// maxIndex = i;
// }
// else if (arr[i] > res && i != maxIndex)
// {
// res = arr[i];
// }
// }
// cout << res << endl;
// }
// return 0;
//}
int main() // 用堆暴力模拟->超时
{int n = 0;// cin >> n;scanf("%d", &n);vector<int> arr(n);for (int i = 0; i < n; ++i){// cin >> arr[i];scanf("%d", &arr[i]);}int q = 0;// cin >> q;scanf("%d", &q);while (q--){int cnt = 0;// cin >> cnt;scanf("%d", &cnt);priority_queue<int> heap;while (cnt--){heap.push(arr[cnt]);}heap.pop();// cout << heap.top() << endl;printf("%d\n", heap.top());}return 0;
}
题解代码:
#include <iostream>
#include <vector>
using namespace std;int main()
{int n = 0;cin >> n;vector<int> arr(n + 1);auto f = arr; // 1到i第一大auto g = arr; // 1到i第二大for(int i = 1; i <= n; ++i){cin >> arr[i];}f[1] = arr[1];for(int i = 1; i <= n; ++i){int x = arr[i];f[i] = max(f[i - 1], x);if(x >= f[i - 1])g[i] = f[i - 1];else if(x >= g[i - 1])g[i] = x;else g[i] = g[i - 1];}int q = 0;cin >> q;while(q--){int n = 0;cin >> n;cout << g[n] << endl;}return 0;
}
dd爱旋转(模拟_有思路不会写)
dd爱旋转
#include <iostream>
#include <vector>
using namespace std;int n = 0;
void func1(vector<vector<int>>& arr) // 列镜像
{for (int j = 0; j < n / 2; ++j){for (int i = 0; i < n; ++i){swap(arr[i][j], arr[i][n - j - 1]);}}
}
void func2(vector<vector<int>>& arr) // 行镜像
{auto tmp = arr;int cnt = 1;for (int i = 0; i < n / 2; ++i){for (int j = 0; j < n; ++j){swap(arr[i][j], arr[n - i - 1][j]);}}
}
int main()
{cin >> n;vector<vector<int>> arr(n, vector<int>(n));for (int i = 0; i < n; ++i){for (int j = 0; j < n; ++j){cin >> arr[i][j];}}int q = 0;cin >> q;int cnt1 = 0, cnt2 = 0;while (q--){int x = 0;cin >> x;if (x == 1) // 顺时针180度,列镜像?{++cnt1, ++cnt2;// func1(arr);// func2(arr);}else // 行镜像{++cnt2;// func2(arr);}}cnt1 %= 2, cnt2 %= 2;if (cnt1)func1(arr);if (cnt2)func2(arr);for (int i = 0; i < n; ++i){for (int j = 0; j < n; ++j){cout << arr[i][j] << " ";}cout << endl;}return 0;
}
DP40小红取数(01背包+同余)
小红取数_牛客题霸_牛客网
原代码:
#include <iostream>
#include <vector>
using namespace std;int main() // dp_背包?
{int n = 0, k = 0;cin >> n >> k;vector<int> arr(n + 1);long long sum = 0, res = 0;for (int i = 1; i <= n; ++i){cin >> arr[i];sum += arr[i];}vector<vector<long long>> dp(n + 1, vector<long long>(sum + 1));// dp[i][j]表示从1到i中选,总和不超过j的最大值(k的倍数->不用)for (int i = 1; i <= n; ++i){for (int j = 0; j <= sum; ++j){dp[i][j] = dp[i - 1][j]; // 不选// if(j >= arr[i] && (dp[i][j - arr[i]] + arr[i]) % k == 0)if (j >= arr[i])dp[i][j] = max(dp[i - 1][j], dp[i][j - arr[i]] + arr[i]);if (dp[i][j] % k == 0)res = max(res, dp[i][j]);// cout << res << " " << i << " " << j << endl;}}//for (int i = 1; i <= n; ++i) // debug//{// for (int j = 0; j <= sum; ++j)// {// cout << dp[i][j] << " ";// }// cout << endl;//}cout << res << endl;return 0;
}
题解及代码:
- 状态定义:首先定义一个二维dp数组,dp[i][j]表示前i个数中除以k的余数为j的当前最大和。
- 状态初始化:0个数时,最大和必为0,所以dp[0][0]=0。
- 状态转移:如果前一个状态余数为j,则更新当前余数为(j+arr[i])%k的情况,要么从余数为j的状态转化过来,要么前一个状态余数也是(j+arr[i])%k,即不选择当前元素。所以dp[i][(int)((j+arr[i])。
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
#define int long long
const int INF = 0x3f3f3f3f3f3f3f3f;signed main() // 01背包+同余
{int n = 0, k = 0;cin >> n >> k;vector<int> arr(n + 1);for (int i = 1; i <= n; ++i){cin >> arr[i];}vector<vector<long long>> dp(N + 1, vector<long long>(N + 1, -INF));// dp[i][j]表示从1到i中选,总和 %k 等于j时,最大和是多少dp[0][0] = 0;for (int i = 1; i <= n; ++i){for (int j = 0; j < k; ++j){dp[i][j] = max(dp[i - 1][j], dp[i - 1][(j - arr[i] % k + k) % k] + arr[i]);}}cout << (dp[n][0] <= 0 ? -1 : dp[n][0]) << endl;return 0;
}
Day39(全不会)
神奇的字母(二)(哈希,更新最大值没把最大值更新,纯菜)
神奇的字母(二)
原代码:
#include <iostream>
#include <string>
#include <vector>
using namespace std;int main()
{vector<int> arr(26, 0);string str;while(getline(cin, str)){for(auto& e : str){if(e != ' ')arr[e - 'a']++;}}int maxVal = arr[0];char ch = 'a';char res = 'a';for(int i = 0; i < 26; ++i, ch++){if(arr[i] > maxVal){// maxVal = arr[i]; 写原代码少了这一句,纯菜res = ch;}}cout << res << endl;return 0;
}
题解代码:
#include <iostream>
#include <string>
#include <vector>
using namespace std;int main()
{vector<int> arr(26, 0);string str;char res = 'a';int maxVal = arr[0];while(getline(cin, str)){for(auto& e : str){if(++arr[e - 'a'] > maxVal){maxVal = arr[e - 'a'];res = e;}}}cout << res << endl;return 0;
}
MT7字符编码(哈夫曼编码,看答案了)
字符编码_牛客题霸_牛客网
#include <iostream>
#include <vector>
#include <string>
#include <queue>
using namespace std;
int main()
{string s;while(cin >> s){// 1. 先统计每个字符的频次int hash[300] = { 0 };for(auto ch : s){hash[ch]++;}// 2. 把所有的频次放⼊堆⾥⾯priority_queue<int, vector<int>, greater<int>> heap;for(int i = 0; i < 300; i++){if(hash[i]){heap.push(hash[i]);}}// 3. 哈夫曼编码int ret = 0;while(heap.size() > 1){int t1 = heap.top();heap.pop();int t2 = heap.top();heap.pop();ret += t1 + t2;heap.push(t1 + t2);}cout << ret << endl;}return 0;
}
DP43最少的完全平方数(知道是背包还不会_写了十来分钟就去吃饭了)
最少的完全平方数_牛客题霸_牛客网
原错误代码:
#include <cmath>
#include <iostream>
#include <vector>
using namespace std;int main()
{// 01背包,dp[i][j] 表示从1到i总和能凑成j的最少个数?int n = 0;cin >> n;int left = sqrt(n);vector<vector<int>> dp(n + 1, vector<int>(n + 1, -0x3f));for(int i = 1; i <= n; i *= i){for(int j = 0; j < i; ++j){dp[i][j] = dp[i - 1][j]; // 不选if(j > i * i)dp[i][j] = min(dp[i][j], dp[i - 1][j - i*i]);}}cout << dp[n][n] << endl;return 0;
}
题解二维代码:
#include <cmath>
#include <iostream>
#include <vector>
using namespace std;int main()
{// 01背包,dp[i][j] 表示从1到i总和能凑成j的最少个数?YES啊int n = 0;cin >> n;// vector<vector<int>> dp(n + 1, vector<int>(n + 1, 0x3f)); // 内存超限int left = sqrt(n);vector<vector<int>> dp(left + 1, vector<int>(n + 1, 0x3f));dp[0][0] = 0;for(int i = 1; i <= left; ++i){for(int j = 0; j <= n; ++j){dp[i][j] = dp[i - 1][j]; // 不选if(j >= i * i)dp[i][j] = min(dp[i][j], dp[i][j - i * i] + 1);}}cout << dp[sqrt(n)][n] << endl;return 0;
}
代码优化成一维:
#include <cmath>
#include <iostream>
#include <vector>
using namespace std;int main()
{int n = 0;cin >> n;vector<int> dp(n + 1, 0x3f);dp[0] = 0;for(int i = 1; i * i <= n; ++i){for(int j = i * i; j <= n; ++j){dp[j] = min(dp[j], dp[j - i * i] + 1);}}cout << dp[n] << endl;return 0;
}
Day40(全不会)
游游的字母串(枚举_没过_菜)
游游的字母串
原菜鸡代码:
#include <iostream>
#include <vector>
using namespace std;int main() // 贪心?
{string str;cin >> str;int n = str.size();vector<int> arr(26);for(auto& e : str){arr[e - 'a']++;}int res = 0x3f;for(auto ch : str){int cnt = 0;for(auto e : str){if(ch == e)continue;char c1 = e, c2 = ch;if(c1 > c2) // 保证c1小swap(c1, c2);int t1 = abs(c1 + 26 - c2);int t2 = abs(c2 - c1);int t = min(t1, t2);if(t > 13)t -= 13;cnt += t * arr[e - 'a'];// cout << ch <<" "<< e <<" "<< t <<" "<< arr[e - 'a'] << endl;}res = min(res, cnt);// cout << res << endl;}cout << res << endl;return 0;
}
题解代码:
#include <iostream>
#include <vector>
using namespace std;int main()
{string str;cin >> str;int res = 1e9;for(char ch = 'a'; ch <= 'z'; ++ch){int cnt = 0;for(auto e : str){cnt += min(abs(e - ch), 26 - abs(e - ch));}res = min(res, cnt);}cout << res << endl;return 0;
}
NC316体育课测验(二)(拓扑排序_没想到_知道也不会)
体育课测验(二)_牛客题霸_牛客网
class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param numProject int整型 * @param groups int整型vector<vector<>> * @return int整型vector*/vector<int> findOrder(int numProject, vector<vector<int> >& groups) {// write code here}
};
原菜鸡代码:
class Solution {
public:vector<int> findOrder(int numProject, vector<vector<int> >& groups) {vector<int> ret(numProject);int i = 0;unordered_set<int> s;for(auto& e : groups){s.insert(e[1]);ret[i++] = e[1];}// cout << s.size() << " " << groups.size() << endl;if(s.size() != groups.size())return {};for(auto& e : groups){s.insert(e[0]);ret[i++] = e[0];}// cout << s.size() << " " << groups.size() << endl;if(s.size() / 2 != groups.size())return {};for(int j = 0; j < numProject; ++j){if(!s.count(j))ret[i++] = j;}return ret;}
};
题解代码:
class Solution {
public:vector<int> findOrder(int numProject, vector<vector<int> >& groups) {vector<vector<int>> edg(numProject);vector<int> in(numProject);for(auto& e : groups){int a = e[0], b = e[1];edg[b].push_back(a); // b->ain[a]++;}queue<int> q;for(int i = 0; i < numProject; ++i){if(in[i] == 0)q.push(i);}vector<int> ret;while(q.size()){int x = q.front();q.pop();ret.push_back(x);for(auto& e : edg[x]){if(--in[e] == 0)q.push(e);}}// if(ret.size() == numProject)// return ret;// return {};return ret.size()== numProject ? ret : (ret.clear(), ret);}
};
DP16合唱队形(不会_以为中间一个是最高的)
合唱队形_牛客题霸_牛客网
原面向测试用例的代码:
#include <iostream>
#include <vector>
using namespace std;int main() // n^2, dp?
{int n = 0;vector<vector<int>> arr(n, vector<int>(2)); // 身高和原本下标for(int i = 0; i < n; ++i){cin >> arr[i][0];arr[i][1] = i;}cout << 0 << endl; // 不会return 0;
}
题解及代码:
#include <iostream>
#include <vector>
using namespace std;int main()
{int n = 0;cin >> n;vector<int> arr(n + 1);for(int i = 1; i <= n; ++i){cin >> arr[i];}vector<int> f(n + 2, 1), g(n + 2, 1); // 最长递增/递减子序列,记得初始化为1for(int i = 1; i <= n; ++i){for(int j = 1; j < i; ++j){if(arr[j] < arr[i]){f[i] = max(f[i], f[j] + 1);}}}for(int i = n; i >= 1; --i){for(int j = i + 1; j <= n; ++j){if(arr[j] < arr[i]){g[i] = max(g[i], g[j] + 1);}}}int len = 0;for(int i = 1; i <= n; ++i){len = max(len, f[i] + g[i] - 1);}cout << n - len << endl;return 0;
}
Day41(就会第一题)
MT2棋子翻转(简单模拟_类似bfs遍历)
棋子翻转_牛客题霸_牛客网
class Solution {
public:vector<vector<int> > flipChess(vector<vector<int> >& A, vector<vector<int> >& f) {int dx[4] = {0, 0, -1, 1};int dy[4] = {1, -1, 0, 0};for(auto& e : f) // 简单模拟{int sr = e[0] - 1, sc = e[1] - 1;for(int i = 0; i < 4; ++i){int x = dx[i] + sr, y = dy[i] + sc;if(x >= 0 && x < 4 && y >= 0 && y < 4){if(A[x][y] == 0)A[x][y] = 1;elseA[x][y] = 0;}}}return A;}
};
宵暗的妖怪(dp_不会)
登录—专业IT笔试面试备考平台_牛客网
题解及代码:
#include <iostream>
#include <vector>
using namespace std;
#define int long longsigned main()
{int n = 0;cin >> n;vector<int> arr(n + 1);for(int i = 1; i <= n; ++i){cin >> arr[i];}vector<int> dp(n + 1);for(int i = 3; i <= n; ++i){dp[i] = max(dp[i - 1], dp[i - 3] + arr[i - 1]); // 不拿和拿}cout << dp[n] << endl;return 0;
}
过桥(贪心+bfs/图论找最短路_不会)
过桥
就输出了负一,没时间想了,题解及代码:
#include <iostream>
using namespace std;
const int N = 2010;
int n;
int arr[N];int bfs()
{int left = 1, right = 1;int ret = 0;while(left <= right){++ret;int r = right;for(int i = left; i <= right; ++i){r = max(r, arr[i] + i);if(r >= n)return ret;}left = right + 1;right = r;}return -1;
}int main()
{cin >> n;for(int i = 1; i <= n; ++i){cin >> arr[i];}cout << bfs() << endl;return 0;
}
Day42(就会第一题)
MT1最大差值(模拟+简单贪心)
最大差值_牛客题霸_牛客网
有一个长为 n 的数组 A ,求满足 0 ≤ a ≤ b < n 的 A[b] - A[a] 的最大值。
给定数组 A 及它的大小 n ,请返回最大差值。
数据范围: 2<n≤2∗10^5,数组中的值满足 0≤∣val∣≤5∗10^8
class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param A int整型vector * @param n int整型 * @return int整型*/int getDis(vector<int>& A, int n) {// write code here}
};
题解代码:
class Solution {
public:int getDis(vector<int>& A, int n) { // Day42_1_滑动窗口?不是// vector<int> arr(n, 0x3f3f3f3f); // 维护一个0到i的最小值// arr[0] = A[0];// int res = 0;// for(int i = 1; i < n; ++i)// {// arr[i] = min(arr[i - 1], A[i]); // 可以用一个变量代替// res = max(res, A[i] - arr[i]);// }// return res;int res = 0, prevMin = A[0];for(int i = 1; i < n; ++i){prevMin = min(prevMin, A[i]);res = max(res, A[i] - prevMin);}return res;}
};
DP44兑换零钱
兑换零钱_牛客题霸_牛客网
题解三个版本代码:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;//二维优化成一维:
int main() // Day42_2_贪心?完全背包?
{int n = 0, aim = 0;cin >> n >> aim;vector<int> arr(n + 1);for(int i = 1; i <= n; ++i){cin >> arr[i];}vector<int> dp(aim + 1, INF);dp[0] = 0;for(int i = 1; i <= n; ++i){for(int j = arr[i]; j <= aim; ++j){dp[j] = min(dp[j], dp[j - arr[i]] + 1); // 选}}cout << (dp[aim] == INF ? -1 : dp[aim]);return 0;
}//原二维代码:
// int main() // Day42_2_贪心?完全背包?
// {
// int n = 0, aim = 0;
// cin >> n >> aim;
// vector<int> arr(n + 1);
// for(int i = 1; i <= n; ++i)
// {
// cin >> arr[i];
// }
// vector<vector<int>> dp(n + 1, vector<int>(aim + 1, INF));
// dp[0][0] = 0;
// for(int i = 1; i <= n; ++i)
// {
// for(int j = 0; j <= aim; ++j)
// {
// dp[i][j] = dp[i - 1][j]; // 不选
// if(j >= arr[i])
// dp[i][j] = min(dp[i][j], dp[i][j - arr[i]] + 1); // 选
// }
// }
// cout << (dp[n][aim] == INF ? -1 : dp[n][aim]);
// return 0;
// }//贪心错解代码
// int main() // Day42_2_贪心?完全背包?
// {
// int n = 0, aim = 0;
// cin >> n >> aim;
// vector<int> arr(n);
// for(int i = 0; i < n; ++i)
// {
// cin >> arr[i];
// }
// sort(arr.begin(), arr.end());// int res = 0;
// int pos = arr.size() - 1;
// while(aim > 0)
// {
// while(pos >= 0 && aim < arr[pos])
// {
// --pos;
// }
// if(pos == -1)
// {
// cout << -1;
// return 0;
// }// res += aim / arr[pos];
// aim %= arr[pos];
// }
// cout << res;
// return 0;
// }
小红的子串(滑动窗口+前缀和思想)
利用前缀和的思想,求种类个数在 [l, r] 区间内子串的个数,等于求 [1, r] 区间内个数 - [1, l - 1] 区间内个数。求种类个数在 [1, count] 区间内子串的个数,可以用滑动窗口来求解。
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;int main() // Day42_3_O(N*logN)?滑动窗口?
{int n = 0, l = 0, r = 0;string str;cin >> n >> l >> r >> str;int res = 0;for(int i = l; i <= r; ++i) // l到r是种类数量,不是长度{int left = 0, right = 0;unordered_map<char, int> flag; // 字母和个数flag[str[left]]++;while(right < n){while(right < n && flag.size() < i) // 进窗口{//cout << right << " " << flag.size() << endl;++right;flag[str[right]]++;// cout << "right" << right << endl;}++res;if(--flag[str[left]] == 0) // 出窗口{flag.erase(str[left]);++left;}++right;}}cout << res << endl;return 0;
}
#include <iostream>
#include <string>
using namespace std;
int n, l, r;
string s;// 找出字符种类在 [1, x] 之间的⼦串的个数
long long find(int x)
{if(x == 0)return 0;// 滑动窗⼝int left = 0, right = 0;int hash[26] = { 0 }, kinds = 0; // 统计窗⼝内字符种类的个数long long ret = 0;while(right < n){if(hash[s[right] - 'a']++ == 0) kinds++;while(kinds > x){if(hash[s[left] - 'a']-- == 1) kinds--;left++;}ret += right - left + 1;right++;}return ret;
}int main()
{cin >> n >> l >> r >> s;cout << find(r) - find(l - 1) << endl;return 0;
}
Day43_都看了题解
kotori和抽卡(⼆)(概率+数学期望)
kotori和抽卡(二)
直接代入高中求概率的公式。
#include <iostream>
using namespace std;int main()
{int n, m;cin >> n >> m;double ret = 1.0;for(int i = n; i >= n - m + 1; i--)ret *= i;for(int i = m; i >= 2; i--)ret /= i;for(int i = 0; i < m; i++)ret *= 0.8;for(int i = 0; i < n - m; i++)ret *= 0.2;printf("%.4lf", ret);return 0;
}
ruby和薯条(排序+二分/滑动窗口)
ruby和薯条
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;int main()
{int n = 0, l = 0, r = 0;cin >> n >> l >> r;vector<int> a(n);for(int i = 0; i < n; ++i){cin >> a[i]; }sort(a.begin(), a.end());long long res = 0;for(int i = 0; i < n; ++i) // 二分{int left = -1, right = -1;auto it1 = lower_bound(a.begin(), a.end(), a[i] + l); // 找第一个大于等于a[i] + l的left = it1 - a.begin();auto it2 = upper_bound(a.begin(), a.end(), a[i] + r); // 找第一个大于a[i] + r的right = it2 - a.begin() - 1;if(left != -1 && right != -1 && right >= left)res += right - left + 1;}cout << res << endl;// int begin = 0, end = 1, res = 0, flag = 0; // 用的滑动窗口,没想到加前缀和,所以错了
// while(begin < end && end < n)
// {
// //cout << begin << " " << end << " res " << a[end] - a[begin] << endl;
// while(end < n)
// {
// //cout << begin << " and " << end << " res " << a[end] << " "<< a[begin] << endl;
// if(a[end] - a[begin] >= l && a[end] - a[begin] <= r)
// {
// ++res;
// if(a[end] - a[begin] == r)
// break;
// }
// ++end;
// }
// ++begin;
// // end = flag;
// end = begin + 1;
// }return 0;
}
AB27 循环汉诺塔(找规律/dp)
循环汉诺塔_牛客题霸_牛客网
#include <iostream>
using namespace std;
const int MOD = 1000000007;
int main()
{int n = 0, x = 1, y = 2;cin >> n;for(int i = 2; i <= n; ++i){int tmpx = x;x = (2 * y + 1) % MOD;y = ((2 * y) % MOD + tmpx + 2) % MOD;}cout << x << " " << y;return 0;
}
Day44_都看了题解
最小差值(排序)
最小差值
排序,然后计算相邻两个数之差的最小值即可。
class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可* 求最小差值* @param a int整型vector 数组a* @return int整型*/int minDifference(vector<int>& a) {sort(a.begin(), a.end());long long res = INT_MAX, n = a.size();for(int i = 0; i < n - 1; ++i){res = min(res, (long long)abs(a[i + 1] - a[i]));}return res;}
};
kotori和素因子
kotori和素因子
正解dfs代码:(下面有错误解法的代码)
#include <iostream>
#include <set>
#include <vector>
#include <cmath>
using namespace std;int ret = 0x3f3f3f3f;
bool use[1007]; // 记录路径中⽤了哪些值
int pathSum; // 记录当前路径中所有元素的和
int n = 0;bool is_prime(int n)
{int i = 0;for (i = 2; i <= sqrt(n); i++){if (0 == n % i)return false;}return true;
}void dfs(vector<int>& a, int pos)
{if(pos == n){ret = min(ret, pathSum);return;}for(int i = 2; i <= a[pos]; i++){if(a[pos] % i == 0 && is_prime(i) && !use[i]){pathSum += i;use[i] = true;dfs(a, pos + 1);pathSum -= i;use[i] = false;}}
}int main()
{cin >> n;vector<int> a(n);for(int i = 0; i < n; ++i){cin >> a[i];}dfs(a, 0);if(ret == 0x3f3f3f3f)cout << -1 << endl;elsecout << ret;return 0;
}
下面方法只是简单地选择第一个未被使用的因子,可能无法找到和最小的最优解(只过了60%)。
#include <iostream>
#include <set>
#include <vector>
#include <cmath>
using namespace std;set<int> s;bool is_prime(int n)
{int i = 0;for (i = 2; i <= sqrt(n); i++){if (0 == n % i)return false;}return true;
}int main()
{int n = 0;cin >> n;vector<int> a(n);for(int i = 0; i < n; ++i){cin >> a[i];}for(auto& e : a){bool flag = false;for(int i = 1; i < e; ++i){if(e % i == 0 && s.find(i) == s.end() && is_prime(i)){s.insert(i);flag = true;break;}}if(flag == false){cout << -1;return 0;}}int res = 0;for(auto& e : s){res += e;}cout << res;return 0;
}
dd爱科学1.0(最长递增子序列贪心)
dd爱科学1.0
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;int main()
{int n = 0;string str;cin >> n >> str;vector<char> arr; // 大小代表最长长度,值代表这个长度的子序列的最后一个值arr.push_back(str[0]);for(int i = 1; i < n; ++i) // 如果大就尾插进arr,小或等就二分插入{if(str[i] >= arr.back()){arr.push_back(str[i]);}else{auto it = upper_bound(arr.begin(), arr.end(), str[i]);if(it != arr.end())*it = str[i];}}cout << n - arr.size();return 0;
}
Day45
kanan和高音(双指针)
kanan和高音
#include <iostream>
#include <vector>
using namespace std;int main()
{int n = 0;cin >> n;vector<int> arr(n);for(int i = 0; i < n; ++i){cin >> arr[i];}int res = 0, left = 0, right = 1;while(right < n){while(right < n && arr[right] - arr[right - 1] <= 8){++right; // 不用加绝对值是低音可以唱}res = max(res, right - left); // right已经多++了,不用再+1left = right;++right;}cout << res;return 0;
}
MT3 拜访(bfs)
拜访_牛客题霸_牛客网
现在有一个城市销售经理,需要从公司出发,去拜访市内的某位商家,已知他的位置以及商家的位置,但是由于城市道路交通的原因,他每次移动只能在左右中选择一个方向 或 在上下中选择一个方向,现在问他有多少种最短方案到达商家地址。
给定一个地图 CityMap 及它的 行长度 n 和 列长度 m ,其中1代表经理位置, 2 代表商家位置, -1 代表不能经过的地区, 0 代表可以经过的地区,请返回方案数,保证一定存在合法路径。保证矩阵的长宽都小于等于 10。
注意:需保证所有方案的距离都是最短的方案
数据范围:2≤n,m≤10
例如当输入为[[2,0,0,0],[0,-1,-1,0],[0,-1,1,0],[0,0,0,0]],4,4时,对应的4行4列CityMap如下图所示:
经理的位置在(2,2),商家的位置在(0,0),经分析,经理到达商家地址的最短方案有两种,分别为:
(2,2)->(2,3)->(1,3)->(0,3)->(0,2)->(0,1)->(0,0)和(2,2)->(3,2)->(3,1)->(3,0)->(2,0)->(1,0)->(0,0),所以对应的返回值为2
在单源最短路的基础上加两个数组维护最短距离和最短路径数量即可,bfs解析代码:
class Solution {
public:int sr, sc, endx, endy, n, m;int dx[4] = {0, 0, -1, 1}; // 方向数组:右、左、上、下int dy[4] = {1, -1, 0, 0};int dist[15][15] = {0}; // 记录到每个位置的最短距离int cnt[15][15] = {0}; // 记录到每个位置的最短路径数量int countPath(vector<vector<int> >& CityMap, int _n, int _m) {// write code heren = _n, m = _m;for(int i = 0; i < n; ++i){for(int j = 0; j < m; ++j){if(CityMap[i][j] == 1)sr = i, sc = j;else if(CityMap[i][j] == 2)endx = i, endy = j;}}return bfs(CityMap);}int bfs(vector<vector<int> >& CityMap){memset(dist, -1, sizeof(dist));dist[sr][sc] = 0;cnt[sr][sc] = 1;queue<pair<int, int>> q;q.push({sr, sc});while(!q.empty()){auto [a, b] = q.front();q.pop();for(int i = 0; i < 4; ++i){int x = a + dx[i], y = b + dy[i];if(x >= 0 && x < n && y >= 0 && y < m && CityMap[x][y] != -1){if(dist[x][y] == -1) // 第⼀次到这个位置{dist[x][y] = dist[a][b] + 1;cnt[x][y] += cnt[a][b];q.push({x, y});}else if(dist[x][y] == dist[a][b] + 1)// 已访问但距离相同(即也是最短路){cnt[x][y] += cnt[a][b]; // 累加路径数}}}}return cnt[endx][endy];}
};
DP33 买卖股票的最好时机(四)
买卖股票的最好时机(四)_牛客题霸_牛客网
#include <iostream>
#include <vector>
using namespace std;
const int N = 1007, INF = 0x3f3f3f3f;
int f[N][N], g[N][N];
// f[i][j]:第i天完成j次交易且持有股票的最大收益
// g[i][j]:第i天完成j次交易且不持有股票的最大收益
int main()
{int n = 0, k = 0;cin >> n >> k;k = min(k, n / 2);vector<int> arr(n);for(int i = 0; i < n; ++i){cin >> arr[i];}f[0][0] = -arr[0];for(int j = 1; j <= k; ++j){f[0][j] = -INF;g[0][j] = -INF;}for(int i = 1; i < n; ++i){for(int j = 0; j <= k; ++j){f[i][j] = max(f[i - 1][j], g[i - 1][j] - arr[i]);g[i][j] = g[i - 1][j];if(j - 1 >= 0)g[i][j] = max(g[i][j], f[i - 1][j - 1] + arr[i]);}}int res = 0;for(int j = 0; j <= k; ++j){res = max(res, g[n - 1][j]);}cout << res << endl;return 0;
}
Day46
AOE还是单体?(贪心)
AOE还是单体?
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;int main()
{int n = 0, x = 0;cin >> n >> x;vector<int> arr(n + 1);for(int i = 1; i <= n; ++i){cin >> arr[i];}sort(arr.begin(), arr.end());int index = max(0, n - x); // 处理 x 过⼤的情况long long ret = arr[index] * x;for(int i = index + 1; i <= n; ++i){ret += arr[i] - arr[index];}cout << ret;return 0;
}
kotori和n皇后(哈希表)
kotori和n皇后
#include <iostream>
#include <unordered_set>
using namespace std;
unordered_set<int> row, col, k1, k2;int main()
{int k = 0, t = 0, x = 0, y = 0;cin >> k;int flag = 0; // 第一个有攻击的位置for(int i = 1; i <= k; ++i){cin >> x >> y;if(flag != 0) // 找到了,只需让其输入即可continue;if(row.count(x) || col.count(y)|| k1.count(x + y) || k2.count(x - y)){flag = i;}row.insert(x);col.insert(y);k1.insert(x + y);k2.insert(x - y);}cin >> t;while(t--){int x = 0;cin >> x;if(flag != 0 && x >= flag)cout << "Yes" << endl;elsecout << "No" << endl;}return 0;
}
NC393 取金币(区间dp)
取金币_牛客题霸_牛客网
class Solution {
public:int getCoins(vector<int>& coins) {int n = coins.size();vector<int> arr(n + 2, 1); // 两段填充1for(int i = 1; i <= n; ++i)arr[i] = coins[i - 1];vector<vector<int>> dp(n + 2, vector<int>(n + 2));for(int i = n; i >= 1; --i){for(int j = i; j <= n; ++j){for(int k = i; k <= j; ++k){dp[i][j] = max(dp[i][j], dp[i][k - 1] + dp[k + 1][j] + arr[i - 1] * arr[k] * arr[j + 1]);}}}return dp[1][n];}
};
Day47
BC138 矩阵转置(线性代数/找规律)
矩阵转置_牛客题霸_牛客网
#include <iostream>
using namespace std;
const int N = 15;
int n, m;
int arr[N][N];
int main()
{cin >> n >> m;for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){cin >> arr[i][j];}}for (int i = 0; i < m; i++){for (int j = 0; j < n; j++){cout << arr[j][i] << " ";}cout << endl;}return 0;
}
四个选项(DFS + 剪枝 + 哈希表)
四个选项
#include <iostream>
#include <vector>
using namespace std;
int cnt[5]; // 用数组存储一个选项出现多少次
int m, x, y;
bool same[13][13]; // 存哪些器的答案是相同的
int ret;
vector<int> path; // 记录路径里面选了哪些选项bool isSame(int pos, int cur)
{for(int i = 1; i < pos; i++){if(same[pos][i] && path[i] != cur)return false;}return true;
}void dfs(int pos)
{if(pos > 12){ret++;return;}for(int i = 1; i <= 4; i++){if(cnt[i] == 0)continue;if(!isSame(pos, i))continue;cnt[i]--;path.push_back(i);dfs(pos + 1);path.pop_back();cnt[i]++;}
}int main()
{for(int i = 1; i <= 4; i++)cin >> cnt[i];cin >> m;while(m--){cin >> x >> y;same[x][y] = same[y][x] = true;}path.push_back(0); // 先放进去⼀个占位符dfs(1);cout << ret << endl;return 0;
}
42. 接雨水(dp/双指针)
42. 接雨水 - 力扣(LeetCode)
class Solution
{
public:int trap(vector<int>& height) {if (height.empty()) return 0;int n = height.size();vector<int> leftMax(n);vector<int> rightMax(n);// 计算每个位置左侧的最大高度leftMax[0] = height[0];for (int i = 1; i < n; ++i) leftMax[i] = max(leftMax[i - 1], height[i]);// 计算每个位置右侧的最大高度rightMax[n - 1] = height[n - 1];for (int i = n - 2; i >= 0; --i) rightMax[i] = max(rightMax[i + 1], height[i]);// 计算每个位置可收集的雨水量int result = 0;for (int i = 1; i < n - 1; ++i) result += min(leftMax[i], rightMax[i]) - height[i];return result;}
};
Day48
疯狂的自我检索者(简单贪心)
疯狂的自我检索者
简单贪心,顺便练了下OJ关流相关模版。
#include <iostream>
#include <vector>
// #include <bits/stdc++.h>using namespace std;
#define int long long
#define endl "\n"
const int INF = 0x3f3f3f3f3f;signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);//cout << 1 << endl << 2 << endl;int n = 0, m = 0;cin >> n >> m;int sum = 0;for(int i = m; i <= n; ++i){int x = 0;cin >> x;sum += x;}cout << double(sum + m) / n << endl;cout << double(sum + m * 5) / n << endl;return 0;
}