Coding Practice,48天强训(23)
Topic 1:打怪(回合数与刀数、先后手关系)
登录—专业IT笔试面试备考平台_牛客网
#include <bits/stdc++.h>
using namespace std;int main()
{int t;cin >> t;while (t--) {int h, a, H, A;cin >> h >> a >> H >> A;int roundM = (H + a - 1) / a; //勇士打掉1只毛球的回合数 向上取整等价ceil(H / a)if (A <= 0 || roundM - 1 <= 0) cout << -1 << endl;else { int x = (h - 1) / ((roundM - 1) * A);//(h-1)保证勇士打完最后一只时血量严格>0cout << x << endl;}}return 0;
}
这题主要的难点在于勇士打完最后一只毛球的边界计算,如intx = 8 / 2,看似勇士能够打4只毛球,但当打完第4只时勇士的血量已经归0,也就意味着最后被计算的那只毛球勇士是没办法打死的,在完成整个击杀动作后,勇士的血量必须严格>0,才能合法的计入击杀数,所以(8 - 1) / 2 = 3,最后一次攻击的过程由于向下取整的特性被垫掉了(勇士在过程中已经死亡,无法完成击杀动作),最后只能打3只,这才是合理的;
Topic 2:字符串的分类(哈希、排序)
字符串分类_牛客笔试题_牛客网
我们说两个字符串是“字母异位词”(Anagrams),比如:"abcd" 和 "dcba" 是异位词,因为都是由 a, b, c, d 组成的;"abc" 和 "cba" 也是异位词;但是 "abc" 和 "abcc" 就不是异位词。
只要一个字符串可以通过“任意交换字符位置”得到另一个,那么它们就是同一类。这跟你怎么交换、交换多少次无关,也可以说,只要两个字符串的组成是一样的,它们就是一类。
怎么快速判断两个字符串是不是同一类?
最简单的方法是把字符串里的字符排序,然后比较排序后的结果。比如:"abcd" 排序后是 "abcd";"dcba" 排序后是 "abcd";"acbd" 排序后是 "abcd",根据ASCII码值排列后,如果字符数量相同,就可以视作一类
#include <bits/stdc++.h>using namespace std;int main()
{int N; // 输入的字符串个数cin >> N;set<string> se; // 用来存放每个“类别”的代表字符串(排序后的字符串)for (int i = 0; i < N; ++i) {string s;cin >> s;sort(s.begin(), s.end()); // 根据ASCII排序se.insert(s); // 放入集合中(集合自动去重)}cout << se.size() << endl; // 输出有多少个不同的类别return 0;
}
代码很简单,主要考察对set容器的理解;
Topic 3:城市群数量
城市群数量_牛客题霸_牛客网
图论,主要考察图的遍历
class Solution
{
public:bool vis[210] = { 0 }; // 标记数组,vis[i] = true 表示节点 i 已被访问int citys(vector<vector<int>>& m) {int res = 0; // 初始化城市群数量为 0int n = m.size(); // 节点数量for(int i = 0; i < n ; ++i) // 遍历所有节点{if(!vis[i]) // 如果节点 i 未被访问过{res++; // 发现一个新的城市群dfs(m, i); // 从节点 i 开始 DFS,标记所有连通节点}}return res; // 返回城市群数量}void dfs(vector<vector<int>>& m, int pos){vis[pos] = true; // 标记当前节点为已访问for(int i = 0; i < m.size() ; ++i) // 遍历所有节点{// 如果节点 i 未被访问且与当前节点 pos 相连if(!vis[i] && m[pos][i]) dfs(m, i); // 递归访问节点 i}}
};