PAT乙级 1065 单身狗 解题思路 代码注释

输入样例:
3
11111 22222
33333 44444
55555 66666
7
55555 44444 10000 88888 22222 11111 23333
输出样例:
5
10000 23333 44444 55555 88888

 

/*
时间:2021年6月20日
思路:
    先看一下大概题意:大概意思就是给出已经 配好对的情侣 然后这些情侣中的某些人和一些其他的人一起出席派对,在这些人中,找出 单身的人 和 没有和自己伴侣一起出席的人

    我们再看需要我们求的是什么:    1)    出席派对单身的人    2)    有伴侣但没有和伴侣一起出席派对的人
    1) + 2) == 我们要求的总数量

    由于情侣是一一配对的,且 ID 必不会重复,所以我们需要一个结构体来存放情侣两个的 ID

    所以我们就至少需要判断两个条件: 1)    这个人是不是有伴侣?        2)    判断这个人是否参加了派对         3)    既有伴侣,又参加派对的话,伴侣有没有出席派对?

    判断是否有伴侣其实很简单,我们只需要在输入的时候,建立一个数组 a[] ,初始化为 0 来做标记,输入 ID 的时候,在数组的对应位置 +1做标记, 又因为 ID 范围是 0~9999,所以这个思路应该是可行的    //    这就完成了    1)有情侣的标记

    接着我们需要标记参加派对的 ID ,和上面标记伴侣是一样的道理,同样在 a[i] 的对应位置做出改变,不同的是,标记参加派对的 ID 不是使用 +1 ,而是 +2 (只要区别于 +1 就可以),因为如果同样是 +1 的话,如果没有情侣的参加派对的人,和有情侣但没有参加派对的人就不能区别了                            //    这就完成了 2)    参加派对的标记
 //    所以到了这一步之后,数组中机会有四种情况,详情看代码注释

    接着我们就需要判断 既有伴侣又参加派对的人,Ta的伴侣有没有参加派对 ,其实也同样不复杂,我们需要思考的就是 如果情侣中只有一人参加派对,他们的标记会是什么样的,和两个人都出席或者两个人都不出席有什么区别
    很明显的,如果两个人都参加或都不参加,那么他们的标记会是一模一样的,所以我们历遍 结构体, 如果他们的 ID 标记是一样的话,同样把他们的 对应位置 做出改变, 同样需要区别于上面两个标记,道理同上    //    这就完成了    3)

    最后我们就只需要历遍数组,找出符合要求的数据,统计个数,输出

*/
 

# include <iostream>
# include <cstdio>
# include <algorithm>
# include <vector>
using namespace std;

int a[100000] = { 0 };	//	一个数组做标记,初始化为 0 

typedef struct Data	//	情侣 ID 一起输入配对放在同一个结构体变量中
{
	int a;
	int b;
}Data;

int main()
{
	int n;
	cin >> n;	//	n 对情侣

	Data *data = new Data[n];	

	for (int i = 0; i < n; i++)
	{
		cin >> data[i].a >> data[i].b;	//	输入
		a[data[i].a]++;	//	每输入一个 ID ,对应位置就 +1
		a[data[i].b]++;	
	}

	int k;	//	输入参加派对的人数
	cin >> k;

	int *c = new int[k];

	for (int i = 0; i < k; i++)	
	{
		cin >> c[i];	//	输入参加派对的 ID 
		a[c[i]] += 2;	//	和上面是同理的,只不过这里是 +2
	}					//	所以此刻整个 数组 会有四种数值分别是
						/*	1)	a[i] == 0 代表没有数据
							2)	a[i] == 1 代表 ID 为 i 的人,有情侣但没有参加派对
							3)	a[i] == 2 代表 ID 为 i 的人,没有情侣,但参加了派对
							4)	a[i] == 3 代表 ID 为 i 的人,既有情侣,也参加了派对
						*/
	for (int i = 0; i < n; i++)	//	里边情侣结构体数组,找出情侣两个人都参加了派对的 ID 
	{							//	找到了 +3
		if (a[data[i].a] == a[data[i].b])
		{
			a[data[i].a] += 3;
			a[data[i].b] += 3;
		}
		else
		{ }
	}					//	所以此刻整个 数组 会有六种数值分别是
						/*	1)	a[i] == 0 代表没有数据
							2)	a[i] == 1 代表 ID 为 i 的人,有情侣但没有参加派对,
							3)	a[i] == 2 代表 ID 为 i 的人,没有情侣,但参加了派对
							4)	a[i] == 3 代表 ID 为 i 的人,既有情侣,也参加了派对,
                                但只是情侣中的一人参加派对
							5)	a[i] == 4 代表 ID 为 i 的人,情侣两人都没有参加派对
							6)	a[i] == 6 代表 ID 为 i 的人,情侣两个人都参加了派对
						*/

	vector<int> v;
	int sum = 0;	//	计数器
	for (int i = 0; i < 100000; i++)	//	我们需要找到参加了派对,但是没有伴侣的 ID
	{									//	也就是当 a[i] == 2 或者 a[i] == 3 的时候
		if (a[i] == 2 || a[i] == 3)
		{
			sum++;
			v.push_back(i);	//	放入容器
		}
	}

	cout << sum << endl;
	for (int i = 0; i < v.size(); i++)
	{
		printf("%05d", v[i]);	//	C++输出有点麻烦,用 printf() 会简单许多
		if (i != v.size() - 1)
			printf(" ");
	}

	delete []data;
	return 0;
}

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值