蓝桥杯暑假训练题1
Posted C_YCBX Py_YYDS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯暑假训练题1相关的知识,希望对你有一定的参考价值。
A 序列求和
略过。。
B k好数
通过dfs搜索,参数记录上个位选择的数字,然后根据上个位选择的数字,判断本位选择的数字,最后可以根据当前状态位于第几个位以及当前的上一个数字选择的是什么来进行记忆化。
#include<bits/stdc++.h>
using namespace std;
const int MOD = 1000000007;
int cnt = 0;
int K,L;
int memo[200][200];
int dfs(int pos,int pre){
if(pos==L)
return 1;
if(pos>L)
return 0;
if(memo[pos][pre])return memo[pos][pre];
int res = 0;
for(int i=0;i<K;i++){
if(i==pre+1 || i == pre-1)continue;
res = (res+dfs(pos+1,i))%MOD;
}
return memo[pos][pre] = res;
}
int main(){
ios::sync_with_stdio(false);
cin>>K>>L;
memset(memo,0,sizeof(memo));
cout<<dfs(0,-1);
}
C 2n皇后问题
n皇后问题的改版,唯一的区别在于,需要把这两种皇后进行区分,并且每次放置不能放在同一个位置,所以可以作为每个行的取两个位置的组合来进行回溯,但是由于两个位置的互换明显也是一个答案,所以应该是选两个位置的排列,故每层回溯都采用两个位置的排列。
#include<bits/stdc++.h>
using namespace std;
int n;
int res = 0;
vector<vector<char> >grid(8,vector<char>(8));
bool check(char c,int row,int col) {
//check上
for(int i=row-1;i>=0;i--) {
if(grid[i][col]==c)
return false;
}//check左上
for(int i=row-1,j=col-1;i>=0&&j>=0;i--,j--) {
if(grid[i][j]==c)
return false;
}//check右上
for(int i=row-1,j=col+1;i>=0&&j<n;i--,j++) {
if(grid[i][j]==c)
return false;
}
return true;
}
//回溯时,'W'表示白皇后,'B'表示黑皇后
void backtrack(int row){
if(row==n){
res++;
return;
}
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
//优先选择白皇后的情况
if(!check('W',row,i))break;
if(grid[row][i]!='0'&&grid[row][j]!='0'&&check('W',row,i)&&check('B',row,j)){
grid[row][i] = 'W';grid[row][j] = 'B';
backtrack(row+1);
grid[row][i] = grid[row][j] = '1';
}
}
}
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
//优先选择黑皇后的情况
if(!check('B',row,i))break;
if(grid[row][i]!='0'&&grid[row][j]!='0'&&check('B',row,i)&&check('W',row,j)){
grid[row][i] = 'B';grid[row][j] = 'W';
backtrack(row+1);
grid[row][i] = grid[row][j] = '1';
}
}
}
}
int main(){
// ios::sync_with_stdio(false);
//输入数据准备回溯
cin>>n;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>grid[i][j];
}
}
backtrack(0);
cout<<res;
}
D 龟兔赛跑预测
此题应采用,同时段的模拟赛跑,只要保证没次龟和兔在同一个时间段(同一层循环),注意当兔子休息的时候,可能乌龟还没有用到所有的休息时长就已经到达终点了,所以当乌龟赢的时候,可以直接采用路程除以乌龟的速度,这样更准确,如果硬要用计时的方式描述乌龟的时间的话,那么需要在兔子休息的时间段,一秒一秒的枚举,而不是一下子过去这么多秒。我这里的代码用的是计时测定乌龟的时间方式。
#include<bits/stdc++.h>
using namespace std;
int v1,v2,t,s,l;
int main(){
ios::sync_with_stdio(false);
cin>>v1>>v2>>t>>s>>l;
int s1=0,s2=0;
int tt = 0;
//龟兔赛跑模拟
for(int i=0;i<l;i++){
if(s2>=l||s1>=l){
break;
}tt++;
if((s1-s2)<t)
s1+=v1;
else{
//这里可能不能直接求,如果在这过程中直接跑过了终点则时间就不对了
if(s2+v2*s<=l){
tt+=s-1;
s2=s2+v2*s;}
else{
tt--;
for (int j = 0; j < s; ++j) {
if(s2>=l)
goto end;
s2+=v2;
tt++;
}
}
continue;
}
s2+=v2;
}
end:
if(s1>s2) {cout<<'R'<<endl;cout<<tt;}
else if(s1<s2) {cout<<'T'<<endl;cout<<tt;}
else {cout<<'D'<<endl;cout<<tt;}
}
E 星际交流
这是一个求数组下一个组合的问题,C++有内置的next_permutation()模板函数,当然也可以自己来实现,这样会快一点点,毕竟STL模板需要满足所有的类型。
- 自己实现next_permutation()
我以前写过博客详解这个函数实现
这也算的上是一个高频面试考点了。
void nextPermutation(vector<int>& nums) {
//找寻nums[i]<nums[j];
int i=nums.size()-1;
for(;i>0;i--){
if(nums[i-1]<nums[i])
break;
}//若为最大排列直接reverse
if(i-1<0){
reverse(nums.begin(),nums.end());
return;
}
//从后往前找寻大于nums[i-1]的数进行交换
for(int j=nums.size()-1;j>i-1;j--){
if(nums[i-1]<nums[j]){
swap(nums[i-1],nums[j]);
reverse(nums.begin()+i,nums.end());
return;
}
}
}
- 解题代码
#include<bits/stdc++.h>
using namespace std;
int N,M;
void nextPermutation(vector<int>& nums) {
//找寻nums[i]<nums[j];
int i=nums.size()-1;
for(;i>0;i--){
if(nums[i-1]<nums[i])
break;
}//若为最大排列直接reverse
if(i-1<0){
reverse(nums.begin(),nums.end());
return;
}
//从后往前找寻大于nums[i-1]的数进行交换
for(int j=nums.size()-1;j>i-1;j--){
if(nums[i-1]<nums[j]){
swap(nums[i-1],nums[j]);
reverse(nums.begin()+i,nums.end());
return;
}
}
}
int main(){
ios::sync_with_stdio(false);
cin>>N>>M;
vector<int> permutation;
permutation.resize(N);
for(int i=0;i<N;i++)cin>>permutation[i];
for (int i = 0; i < M; ++i) {
nextPermutation(permutation);
}
for(int i=0;i<N;i++)
cout<<permutation[i]<<' ';
return 0;
}
F 统计单词个数(大佬求教,这题没看懂)
这题不会,题目也没看懂。。。。求大佬指点!!!
G 接水问题
由于此题的接水的顺序已经给你固定了,那么当水龙头都已经满了,那下一个接水的会跑到哪一个水龙头上去呢?答案肯定是耗时最小的那个,如果把整个接水的过程看作同一时刻的延续,那么只需要将下一个来接水的接水时间加上原来上一个接完水用的时间即可,然后再从这里面挑时长最少的一个,再进行累加,以此类推,直到所有的人都接完水,我们只需要查看哪个水龙头的接水时间最长,这就是最终所需的接水时间。
#include<bits/stdc++.h>
using namespace std;
int n,m;
int findMin(vector<int>&people){
int min = INT_MAX;
int pos;
for(int i=0;i<m;i++){
if(people[i]<min){
min = people[i];
pos = i;
}
}
return pos;
}
int main(){
ios::sync_with_stdio(false);
//解题策略,先确认一个满队,无法形成一个满队,我们就直接输出,打水的最大值即可。
//根据满队的最小值确认下一个续接的位置,所以直接上下一个到该位置,下次的操作也是这样,一直到所有的人都接完,这些元素中最大的那个就是答案
cin>>n>>m;
vector<int>people(n);
for(int i=0;i<n;i++)cin>>people[i];
if(n<=m)
cout<<*max_element(people.begin(),people.end());
else{
int cnt = m;
while(1){
if(cnt>=n)
break;
int pos = findMin(people);
people[pos] += people[cnt++];
}
cout<<*max_element(people.begin(),people.begin()+m);
}
return 0;
}
H Hanoi问题
此题的汉诺塔问题,要求可以一下子带上多个盘子移动,所以我们把它视作一个可根据m优化的汉诺塔问题即可,最终根据m可以视作几个盘子,那么就是几个汉诺塔问题。
- 关于汉诺塔问题的求解,我之前写过一篇博客(如果只是求数量的话还是挺简单的递推)
汉诺塔问题详解
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,m;
ll hanoi(int t){
ll cur = 1;//f(1)
for(int i=1;i<t;i++){
cur = 2*cur+1;
}
return cur;
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>m;
int q;
if(n%m)
q = n/m + 1;
else
q = n/m;
cout<<hanoi(q);
return 0;
}
以上是关于蓝桥杯暑假训练题1的主要内容,如果未能解决你的问题,请参考以下文章
BUCTOJ - 2023上半年ACM&蓝桥杯每周训练题-1-A~K题C++Python双语版