牛客小白月赛99(A~F)

2024-08-26 10:52
文章标签 牛客 99 小白月赛

本文主要是介绍牛客小白月赛99(A~F),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 写在前面
  • A 材料打印
    • 思路
    • code
  • B %%%
    • 思路
    • code
  • C 迷宫
    • 思路
    • code
  • D 又是一年毕业季
    • 思路
    • code
  • E 多米诺骨牌
    • 思路
    • code
  • F 自爆机器人
    • 思路
    • code

牛客小白月赛99

写在前面

这次的小白月赛题目出的挺好,很多算法知识都有涉及到,E题这种题型我还是第一次遇到,也是学到了一些有用的算法知识

A 材料打印

思路

签到题,考虑2种情况:

  • 彩印比黑白更便宜,全部印彩印
  • 黑白比彩印更便宜,黑白和彩印都选

code

void solve(){int a,b,c,d;cin >> a >> b >> c >> d;if(c>=d){cout << (a+b)*d << endl;return ;}cout << a*c+b*d << endl;return ;
}

B %%%

思路

观察样例不难发现,每次都取自身的一半
在操作过程中,若n可以被2整除,我们需要将n除以2后在减去1,反之,直接除以2即可

code

void solve(){int n;cin >> n;int cnt=0;while(n){if(n%2==0){n/=2;n--;} else n/=2;cnt++;}cout << cnt << endl;return ;
}

C 迷宫

思路

考点:搜索

这道题需要用到2次搜索(bfs或者dfs都行)

先从终点进行搜索,搜索上下左右四个方向,搜索到当前坐标为 ‘#’ ,则将这个坐标的行和列都进行标记(正向搜索需要用到)

然后我们再从起点进行搜索,每次都在 ‘.’ 的坐标进行搜索,如果当前行或者列被标记过,则说明可以用激光将这一行或者一列都清除掉,直接输出YES

如果搜索结束还未找到终点以及被标记的行或者列,那就输出NO

code

const int N=1e3+5;
int v[N][N],fx[N],fy[N];
char a[N][N];
int sx,sy,ex,ey;
int n,m,flag=0;
int dx[4]={1,0,0,-1};
int dy[4]={0,1,-1,0};
struct node{int x,y;
};
void bfs1(int x,int y){queue<node> q;q.push({x,y});v[x][y]=1;while(!q.empty()){int x=q.front().x,y=q.front().y;q.pop();if(a[x][y]=='S'){flag=1;return ;}for(int i=0;i<=3;++i){int tx=x+dx[i];int ty=y+dy[i];if(tx<1||ty<1||tx>n||ty>m) continue;if(a[tx][ty]=='#') fx[tx]=1,fy[ty]=1;if(a[tx][ty]=='#' || v[tx][ty]) continue;v[tx][ty]=1;q.push({tx,ty});}}
}
void bfs2(int x,int y){memset(v,0,sizeof v);queue<node> q;q.push({x,y});v[x][y]=1;while(!q.empty()){int x=q.front().x,y=q.front().y;q.pop();if(fx[x] || fy[y]){cout << "YES" << endl;exit(0);}for(int i=0;i<=3;++i){int tx=x+dx[i];int ty=y+dy[i];if(tx<1||ty<1||tx>n||ty>m) continue;if(a[tx][ty]=='#' || v[tx][ty]) continue;v[tx][ty]=1;q.push({tx,ty});}}
}
void solve(){cin >> n >> m;for(int i=1;i<=n;++i)for(int j=1;j<=m;++j){cin >> a[i][j];if(a[i][j]=='S') sx=i,sy=j;if(a[i][j]=='E') ex=i,ey=j;}bfs1(ex,ey);if(flag){cout << "YES" << endl;return ;}bfs2(sx,sy);cout << "NO" << endl;return ;
}

D 又是一年毕业季

思路

思维题,我们选择的拍照时间的因子中不能存在是某个人眨眼睛的时间
很显然我们就会想到素数,我们只需要找个最小的没有出现过的素数

由于n的范围在2e5,显然我们可以进行暴搜
先用筛法将素数找出来,接着遍历2e5+1个素数,找最小的没有出现过的素数就行了

code

const int N=1e7+5;
int prime[N],v[N];
void ola(){memset(v,true,sizeof v);v[1]=v[0]=false;int k=0;for(int i=2;i<=N;++i){if(v[i]){prime[++k]=i;}for(int j=1;prime[j]*i<=N;++j){v[prime[j]*i]=false;if(i%prime[j]==0) break; }}
}
void solve(){int n;cin >> n;map<int,int> m;for(int i=1;i<=n;++i){int x;cin >> x;m[x]=1;}for(int i=1;i<=2e5+1;++i){if(!m[prime[i]]){cout << prime[i] << endl;break;}}return ;
}

E 多米诺骨牌

思路

考点:区间合并(贪心)

区间合并的板子题,将这些骨牌按左边界,然后遍历这些骨牌,每次遍历都让计数器k++
如果上一个骨牌的右边界大于等于当前骨牌的左边界,则更新当前右边界为max(当前骨牌的右边界,原右边界)
反之,将计数器k存入数组里面,更新左边界为当前左边界,更新右边界为当前骨牌的右边界,k清零
最后将最后一个合并的骨牌存入到数组里

将数组进行降序排序,如果m大于等于数组的长度,直接输出n
反之,输出0~m-1 下标的数组总和

code

const int N=1e6+5;
vector<PII> a;
vector<int> res;
int n,m;
void merge(){sort(a.begin(),a.end());int k=0;int st=-2e9,ed=-2e9;for(auto u : a){k++;if(ed<u.fi){if(st!=-2e9) res.push_back(k);st=u.fi,ed=u.se;k=0;}else ed=max(ed,u.se);}if(st!=-2e9) res.push_back(k+1);
}
void solve(){cin >> n >> m;a.resize(n);res.clear();for(int i=0;i<n;++i){int x;cin >> x;a[i].se=x;} for(int i=0;i<n;++i){int x;cin >> x;a[i].fi=x;a[i].se+=a[i].fi;}merge();sort(res.begin(),res.end(),greater<int>());if(m>=res.size()){cout << n << endl;} else{int ans=0;for(int i=0;i<m;++i){ans+=res[i];}cout << ans << endl;}return ;
}

F 自爆机器人

思路

考点:背包DP

这题其实不难,难点在于如何将来回走动的时间抽象为完全背包的问题

先考虑无解的情况,如果 n > t n>t n>t ,自然答案就为0
那么其他情况都是有解的,这个机器人最少也能对怪物造成n点伤害
那么剩下 t − n t-n tn 的时间该怎么算呢,我们在回头细看题目
这个机器人能在任意两堵墙之间来回走动,实际上我们只要让他在相邻的两堵墙之间来回走动即可

举个栗子:3 4 8
这个机器人可以选择在3 4进行移动,我们需要考虑来回,那么它所消耗的时间就为2*(4-3)=2
同理,我们也可以选择在3 8进行移动,它消耗的时间为2*5=10
但是我们选择3 8进行移动和3 4 + 4 8 进行移动所消耗的时间是相同的,因此我们只需要考虑相邻的两堵墙即可

由于它可以无限次进行移动,不难想到完全背包,来回移动消耗的时间既是重量也是价值
开一个f数组存它的价值,它的上限就为 t − n t-n tn ,我们只需要考虑 f [ t − n ] f[t-n] f[tn] 的最大价值即可

最后输出 n + f [ t − n ] n+f[t-n] n+f[tn]

code

const int N=2e5+5;
int a[N],f[N];
void solve(){set<int> s;int n,m,t;cin >> n >> m >> t;for(int i=1;i<=m;++i) cin >> a[i];if(n>t){cout << 0 << endl;return ;}sort(a+1,a+1+m);int ans=t-n;for(int i=1;i<=ans;++i) f[i]=0;for(int i=1;i<m;++i){s.insert(2*(a[i+1]-a[i]));}for(auto x : s)for(int j=x;j<=ans;++j){f[j]=max(f[j],f[j-x]+x);}cout << n+f[ans] << endl;return ;
}

这篇关于牛客小白月赛99(A~F)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1108357

相关文章

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

牛客小白月赛100部分题解

比赛地址:牛客小白月赛100_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A.ACM中的A题 #include<bits/stdc++.h>using namespace std;#define ll long long#define ull = unsigned long longvoid solve() {ll a,b,c;cin>>a>>b>

牛客小白月赛100(A,B,C,D,E,F三元环计数)

比赛链接 官方讲解 这场比较简单,ABC都很签到,D是个不太裸需要预处理的 B F S BFS BFS 搜索,E是调和级数暴力枚举,F是三元环计数。三元环考的比较少,没见过可能会偏难。 A ACM中的A题 思路: 就是枚举每个边变成原来的两倍,然后看看两短边之和是否大于第三边即可。 不能只给最短边乘 2 2 2,比如 1 4 8 这组数据,也不能只给第二短边乘 2 2 2,比

笔试强训,[NOIP2002普及组]过河卒牛客.游游的水果大礼包牛客.买卖股票的最好时机(二)二叉树非递归前序遍历

目录 [NOIP2002普及组]过河卒 牛客.游游的水果大礼包 牛客.买卖股票的最好时机(二) 二叉树非递归前序遍历 [NOIP2002普及组]过河卒 题里面给的提示很有用,那个马的关系,后面就注意,dp需要作为long的类型。 import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息publ

每日OJ_牛客_求和(递归深搜)

目录 牛客_求和(递归深搜) 解析代码 牛客_求和(递归深搜) 求和_好未来笔试题_牛客网 解析代码         递归中每次累加一个新的数,如果累加和大于等于目标,结束递归。此时如果累加和正好等于目标,则打印组合。向上回退搜索其它组合。此题本身就是一个搜索的过程,找到所有的组合。 #include <iostream>#include <cmath>#in

牛客《剑指Offer》 -- 数值的整数次方

题目描述 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。 思路 特别注意负数的情况,出现负数,将其转化为正数然后求倒数。 class Solution {public:double Power(double base, int exponent) {double total = 1;bool flag = false

牛客网《剑指Offer》 二进制中1的个数

题目描述 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。 思路 负数用补码,其实就是求一个数据在计算机中是存储是怎么样子的。用位运算,就能很好实现。 class Solution {public:int NumberOf1(int n) {int count = 0;int flag = 1;while (flag != 0) {if ((n & f

牛客网《剑指Offer》 矩形覆盖

题目描述 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? class Solution {public:int rectCover(int number) {if(number==0) return 0;if(number==1) return 1;if(number==2) return 2;retu

牛客《剑指Offer》 变态跳台阶

题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。 思路 根据 普通的跳台阶可以总结出 f(n) = f(n-1) + f(n-2) +f(n-3) + 。。。。+ f(1) +1 不妨设 f(0) = 1 , 则易得 class Solution {public:int jumpFloorII(int n

牛客《剑指Offer》 跳台阶

题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。 思路 递归思想,n阶梯子走法等于n-1 加上n-2的。 class Solution {public:int jumpFloor(int number) {if(number==1) return 1;if(number==2) return 2;return jumpFl