AtCoder ABC002 A,B,C,D题

这篇博客详细介绍了AtCoder ABC002的四道题目,包括A题中使用max和min函数判断最大值和最小值,B题的字符过滤,C题利用平面三角形面积公式求解,以及D题通过位运算解决复杂逻辑。文章还分享了位运算的小技巧,如快速生成全1二进制数和检查二进制位的方法。
摘要由CSDN通过智能技术生成

A题:推荐使用max函数,可以判断最大值。

max格式:max(a,b),表示a,b的最大值。

求最小值的min,用法与max相同。

min格式: min(a,b),表示a,b的最小值。

#include<bits/stdc++.h>
usingnamespacestd;
int a,b;
int main()
{
	cin>>a>>b;
	cout<<max(a,b)<<endl;
}

B题:

每次读入一个字符,如果这个字符不是 a,e,i,o,中的一个,就输出。

记得最后要输出换行。

#include<iostream>
using namespace std;
char c;
int main()
{
   while(cin>>c)//教大家一个实用的方法,在for或while循环里,条件是cin时,成功输入会返回1,未输入会返回0。
   {
       if(c!='a'&&c!='e'&&c!='i'&&c!='o'&&c!='u') 
       {
          cout<<c;
       }
   }
   cout<<endl;
}

C题:

平面内求三角形面积公式如下:((x1y2-x2y1)+(x2y3-x3y2)+(x3y1-x1y3))/2

这个公式必须要将点按顺序排列,但是我们可以不排列,当结果小于0的时候,直接输出相反数

#inlcude<biits/stdc++.h>
using namespace std;
int main()
{
	double x1,y1,x2,y2,x3,y3;
	cin>>x1>>y1>>x2>>y2>>x3>>y3;
	double sum=((x1*y2-x2*y1)+(x2*y3-x3*y2)+(x3*y1-x1*y3))/2;
	if(sum>0) cout<<sum;
	else cout<<-sum;
	return 0;
}

D题:

看到此题我的第一反应是并查集,但做着做着就发现并查集好像无法判断彼此了解这件事情。

看了一眼数据范围,发现 n 很小,2^n 也不过 40000000 多,想到可以用状态压缩。

每个人选或不选!

具体来说,一个状态 st可以表示为一个 n位的二进制数,从右到左第 i位为 1,表示选择第 i个人;反之,不选择第 i个人。

举个栗子,n = 3, st = 011,表示一共 3 个人,选择第 1, 2 个人的状态。

状态设计好了,那最终答案是选哪个状态呢?

由于 2^n 只有 40000000多,所以枚举是没有问题的。于是我们把 0∼(2n−1) 的状态全部枚举一遍。

如何判断合不合法?

我们可以枚举 st 中的每一位,如果是 1 就把他存进 vector。

存完了以后再 n^2 枚举 vector 内的任意两个元素。如果所有二元组都互相了解,那么合法,更新答案即可。

最后说一下初始化,每读入两个人 (x, y),那么 G[x][y] = G[y][x] = 1,同时别忘了把每个 G[i][i] 都设为 1(每个人都认识自己)。

别忘了!每次考虑完一个状态以后要 st ++ !


位运算小技巧

此题使用位运算可以很大程度上减小码量。

例如:

  • 2^n - 1没必要写循环,直接 (1 << n) - 1 即可。(左移/右移)

  • 判断 st 第 i 位(从右到左)是否为 1,只需要把 st和 2^i按位与一下即可,若结果为 1表示第 i位为 1,反之同理。即:st & (1 << i)

#include<bits/stdc++.h>
#define _for(i, a, b)  for (int i = (a); i <= (b); i ++ )
using namespace std;
const int N = 15;
int n, m, ans, G[N][N];
int main(){
	cin >> n >> m;
	int a, b;
	_for (i, 0, n - 1)  G[i][i] = 1;  // 自己认识自己 
	_for (i, 1, m) {
		cin >> a >> b, a -- , b -- ;
		G[a][b] = G[b][a] = 1;  // 两点之间有连边 
	}
	int st = 0;
	while (st <= (1 << n) - 1) {  // 遍历每一个状态 
		vector<int> v;
		_for (i, 0, n - 1)
			if (st & (1 << i))  v.push_back(i);  // 把选出的点存入 
		int bj = 1;  // 标记 
		for (int x : v)  for (int y : v)
			if (! G[x][y]) { bj = 0; break; }  // 如果有两人不认识,散伙 
		if (bj == 1)  ans = max(ans, (int)v.size());  // 更新答案(最多人数) 
		st ++ ;  // 别忘了更新状态 
	}
	cout << ans << endl;
	return0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值