PAT (Basic Level) Practice (中文)1065 单身狗 (25 分)

该博客介绍了如何解决PAT(BasicLevel)Practice中的1065题——单身狗问题。博主通过C++编程,利用map和set数据结构,找出大型派对中单身及伴侣不在场的客人。关键步骤包括存储夫妻关系、找出落单客人并按升序输出。博客还分享了在处理ID为0时的注意事项以及可能的优化方法。

PAT (Basic Level) Practice (中文)1065 单身狗 (25 分) 凌宸1642

题目描述:


“单身狗”是中文对于单身人士的一种爱称。本题请你从上万人的大型派对中找出落单的客人,以便给予特殊关爱。

输入格式:


输入第一行给出一个正整数 N(≤ 50 000),是已知夫妻/伴侣的对数;随后 N 行,每行给出一对夫妻/伴侣

——为方便起见,每人对应一个ID 号,为 5位数字(从0000099999),ID间以空格分隔;

之后给出一个正整数M(≤ 10 000),为参加派对的总人数;随后一行给出这M位客人的 ID,以空格分隔。

题目保证无人重婚或脚踩两条船。

输出格式:


首先第一行输出落单客人的总人数;随后第二行按ID递增顺序列出落单的客人。

ID间用 1 个空格分隔,行的首尾不得有多余空格。

输入样例:


3
11111 22222
33333 44444
55555 66666
7
55555 44444 10000 88888 22222 11111 23333

输出样例:


5
10000 23333 44444 55555 88888

题目要求:


作者     			CHEN, Yue
单位      		浙江大学
代码长度限制        16 KB
时间限制           200 ms
内存限制           64 MB

坑点:


  1. 对于夫妻客人的存储的时候,首先我也选择了使用map<int , int > 但是题目中 客人 的 ID 值可以是0,

这会出现什么问题呢? 若刚好某个人的 ID 值是 0 的话,当我们查找 map的时候,返回的0 值 不好判断

是没有这个客人 , 还是找到了符合要去的对象 ID 解决方法很简单,可以多输入的时候如果 ID0 的话

我们转化为另外一个数即可,但这样会需要增加很多的判断,所以我采用了 map<string , string>

  1. 存储那些 有对象但是不确定其对象是否在场的时候,我首先采取的是,直接使用 vector 来进行存储,

    在检查其对象是否在场的时候,会需要依次比对(就算使用 sort函数,写二分查找 也会耗很多时间) ,

    (题主注意是,没有去尝试用二分,所以运行超时了)。 所以选择了直接再用一个 map<string , int>

    注意找不到的时候会返回 0,所以我们int 存储时,不能存储0

  2. 如果这样还是会超时的话, 就将所有的cin cout 换成 scanf printf

    这里需要知道的是,利用 scanf 进行输入 string 类型时,需要确定分配内存的大小,不然会报错

    然后进行 printf输出 string 类型的时候,要利用c_str() 函数,转换为字符数组输出。

解题思路:


存储各夫妻对应关系

/*
	1. 一看题目找 单身狗 ,瞬间觉得好简单,不就是把没有 对象 的人拎出来,哈哈哈哈哈
	题目中明确没有一个人有两个人对象的情况,那么久可以很自然的想到一对夫妻是一一对应的。
	一对一对的存储,很容易想到使用 map 来存储夫妻的 key 和 value ,
	而题目中明确说明,夫妻是一一对应的,也就是 可以通过 value 找到 key ,
	所以说如一对夫妻的时候,我们就把 夫妻分别作为 key 和 value 的 map 存储起来。
	至于 map 中的数据类型,我选择了使用 string 对应 string
*/
a.resize(5);
b.resize(5);
t.resize(5); // 重新分配内存,为了使用 scanf 对 string 类型进行输入。
while(n--){
	scanf("%s %s" , &a[0] , &b[0]) ;
	mp.insert(pair<string , string>( a , b )) ; // 插入《夫,妻》
	mp.insert(pair<string , string>( b , a )) ;	// 插入《妻,夫》
}

找出落单客人

/*
	2. 然后就应该是找出里面的单身狗啦	这一步的处理,我分成了两部分来进行。
	第一部分,这里需要理解好 落单客人 和 单身狗 的区别。
	落单客人 包括 单身狗 以及 有对象但是其对象不在现场的客人。
	存储满足要求的落单客人 输出时要按照 ID 的升序,故采用 set 容器进行存储
*/
	for(int i = 0 ; i < k ; i ++){
		scanf("%s" , &t[0]) ; 
		if(mp[t] == "")  // 如果夫妻关系 map 里面没有这个人的对象,那么他是单身狗,符合要求,加入 st
            st.insert(t) ;
		else { // 如果他是有对象的人,先记录下来,待会再来检查一下他对象在不在场
			cus.push_back(t) ;
			test.insert(pair<string , int>(t , i + 1)) ; // 给他安排一个序号 (从 1 开始)
		}
	}

/*
	第二部分,就是从第一部分里面记录的有对象的客人,如果他的对象不在场,那么久加入落单客人行列中。
	
		在 mp 中找到 cus[i] 的夫/妻的 ID,根据此 ID 查找我们第一部分时给他的序号 ,
    	若果序号不为 0 说明 他们夫妻均在场 (找不到序号的时候返回 0 )
    	找不到序号的时候,那就说明他今晚是 落单客人,得加入 落单客人 的行列中。
*/
for(int i = 0 ; i < cus.size() ; i++)	
	if(test[mp[cus[i]]] != 0) 
		continue ;
	else st.insert(cus[i]) ;

按要求输出落单客人 ID

	printf("%d\n" , st.size()) ; // 打印落单客人的人数
	int i = 1 ;
	// 通过迭代器访问 set 中的元素
	for(set<string>::iterator it = st.begin(); it != st.end() ;i++, it++){
		printf("%s%c",(*(it)).c_str() , (i != st.size())?' ':'\n');
	}

完整代码


#include<bits/stdc++.h>
using namespace std ;
map<string , string> mp ;
map<string , int> test ;
set<string> st ;
vector<string> cus ;
int n , k ;
string a , b , t ;
int main(){
	scanf("%d" , &n) ;
	a.resize(5) ;
	b.resize(5) ;
	t.resize(5) ;
	while(n--){
//		scanf("%d %d", &a , &b ) ;
		scanf("%s %s" , &a[0] , &b[0]) ;
		mp.insert(pair<string , string>(a , b)) ;
		mp.insert(pair<string , string>(b , a)) ;	
	}
	scanf("%d" , &k) ;
	for(int i = 0 ; i < k ; i ++){
		scanf("%s" , &t[0]) ; 
		if(mp[t] == "") 
            st.insert(t) ;
		else {
			cus.push_back(t) ;
			test.insert(pair<string , int>(t , i + 1)) ;
		}
	}
//	for(int i = 0 ; i < cus.size() ; i++){
//		cout<<cus[i]<<endl ;
//	}
	for(int i = 0 ; i < cus.size() ;i ++)	
		if(test[mp[cus[i]]] != 0) continue ;
		else st.insert(cus[i]) ;
	printf("%d\n" , st.size()) ;
	int i = 1 ;
	for(set<string>::iterator it = st.begin() ; it != st.end() ;i++ , it++)
		printf("%s%c" , (*(it)).c_str() , (i != st.size())?' ':'\n') ;
	return 0 ;
}

其他博客

### 关于PAT Basic Level Practice的测试点及题目解析 #### 题目难度PAT(Programming Ability Test)是由浙江大学举办的计算机程序设计能力考试,为不同级别。其中乙级即Basic Level主要面向初学者,考察基本编程技能[^1]。 #### 测试点特点 对于PAT Basic Level中的某些特定题目而言,其测试点设置较为严格。例如,在处理字符串匹配类问题时,需要注意算法逻辑中何时应当终止循环以防止不必要的重复计算;而在涉及数值运算的问题里,则可能因为边界条件而增加复杂度[^3]。 #### 编程语言的选择影响 值得注意的是,尽管大部简单题目可以作为学习某种新语言的良好实践材料,但在实际操作过程中可能会遇到由于所选语言特性而导致难以通过全部测试点的情况。比如Java在面对部效率敏感型试题时表现不佳,这可能是由于该语言本身的执行速度相对较慢以及内存管理方式等因素造成的。因此有时不得不转而采用其他更适合解决此类问题的语言版本来完成解答[^2]。 ```cpp #include<bits/stdc++.h> using namespace std; int a[100000]; int c=1; void getPrime(){ int flag=0; for(int i=2;i<105000;i++){ flag=1; for(int j=2;j<=sqrt(i);j++){ if(i%j==0){ flag=0; break; } } if(flag==1) a[c++]=i; } } int main(){ int m,n,i,t=1; scanf("%d %d",&m,&n); getPrime(); for(i=m;i<=n;i++){ if(t%10==1){ printf("%d",a[i]); t++; }else{ printf(" %d",a[i]); t++; } if((t-1)%10==0) printf("\n"); } return 0; } ``` 上述C++代码展示了如何实现个简单的质数打印功能,并且针对输出格式进行了特殊处理以满足特定要求。这段代码很好地体现了编写高效解决方案的重要性,尤其是在应对像PAT这样的在线评测系统时[^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lingchen0522

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值