一、打怪
思路
由于是先手攻击,如果一次攻击就能杀死小怪,那么说明可以为无限杀小怪。
再计算杀一只小怪要扣多少血就好了,再用总生命值去除这个扣血量,得到的就是最多杀死小怪的数量。注意,由于最后一定要活下来,最少要保留一滴血。我们可以拿h-1去计算就好了。
时间复杂度O(1),总时间复杂度O(t)。
代码:
#include <iostream>
using namespace std;
int main() {
int t;
cin>>t;
while(t--){
int h,a,H,A;
cin>>h>>a>>H>>A;
if(a>=H){
cout<<"-1";
if(t)cout<<endl;
continue;
}
int k1=(H+a-1)/a;//几个回合杀死小怪
int c=(k1-1)*A;//每杀死一个小怪寇多少血
cout<<(h-1)/c;
if(t)cout<<endl;
}
return 0;
}
// 64 位输出请用 printf("%lld")
二、字符串分类
思路
思考这样一个结论:一个字符串如果可以任意交换相邻位置,代表这个字符串可以随意排列。
即如果字符串A和字符串B有一样种类的字符且每种字符数量都相等。那么AB一定可以通过交换位置变成相等。
所以我们只需要比较AB每一种字符的数量和种类是否相等就好了。
给出一个技巧,直接将AB排序之后比较看是否一样就好了。时间复杂度为O(nlogm),m为字符串长度。
代码:
#include <iostream>
#include<unordered_map>
#include<string>
#include<algorithm>
using namespace std;
const int N=60;
int main() {
int n;
cin>>n;
string str;
int ans=0;
unordered_map<string,int> mp;
for(int i=1;i<=n;i++){
cin>>str;
sort(str.begin(),str.end());
if(!mp.count(str)){
ans++;
mp[str]++;
}
}
cout<<ans<<endl;
return 0;
}
三、城市群的数量
思路
并查集。染色搜索也行。
每次将一条边上的两个点加入到一个集合里面,最后计算集合的·数量就好了。数组p[i]的值表示 i节点所在集合的编号。初始时所有的城市所在集合编号就是他自己。
代码:
class Solution {
public:
int find(int x,vector<int>& p){
if(p[x]!=x)p[x]=find(p[x],p);
return p[x];
}
int citys(vector<vector<int> >& m) {
int n=m.size();
vector<int> p(n+1);
for(int i=1;i<=n;i++)p[i]=i;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(m[i][j]==1){
int x=find(i+1,p);
int y=find(j+1,p);
if(x==y)continue;
p[x]=y;
}
}
}
int ans=n;
for(int i=1;i<=n;i++){
if(p[i]!=i)ans--;
}
return ans;
}
};