杭电计算机2013年硕士研究生复试第二题详解

题目简介

一个活动有N个人参加,一个主持人和N-1个普通参加者,其中所有的人都认识主持人,主持人也认识所有的人,主持人要求N-1个参加者说出他们在参加者中所认识的人数,如果A认识B,则B认识A,所以每个参赛者最少是会认识一个人,就是主持人。输入每个参赛者所认识的人数后,需要判断他们中有没有人说谎。

input 

第一行是N,N=0表示结束 
第二行是N-1个数字 ,第n个数字表示第n个参赛者所认识的人的数目

Output

true或者false

input sample


1 2 4 5 5 3


3 7 7 7 7 5 6 6 

output sample

false

true

解题思路

我们可以把每个参赛者认识的人用一个vectro<int> friendNum来保存。然后我们一个一个的判断第i个人有没有骗人。

我在这里说明一下friendNum的意义:friendNum[i]表示第i个人所认识的朋友的个数;friendNum.size()其实就是剩余参赛者的数目。(为什么说是剩余呢?因为可能有的参赛者一个人都不认识,同时当剩余的人为0时就是没人骗人)

那么,我们如何知道滴i个人没骗人呢?很简单如果friendNum[i] <= friendNum.size()-1就可以了(ps:这里的人就是指参赛者,主持人可以看做一个特殊的参赛者),如果第i个人没有骗人我们就将他从friendNum中移出去。同时将剩余的friendNum[i]个参赛者所认识的人的个数减1,因为可以假定他们都认识地i个参赛者。(为什么可以假定?这个。。我不好解释,你想不明白的话我也没办法了)

最后如果有人只认识一个人,减1以后就没用认识的人了也需要将其移出去。

源代码

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

bool cmp(int a, int b)
{
	return a < b;
}

void eraseZero(vector<int> & v)
{
	for(int i = 0; i < v.size(); i++)
	{
		if(v[i] == 0)
		{
			v.erase(v.begin()+i);
			i--;
		}
	}
}

int main()
{
	int n;
	vector<int> friendNum;     //每个人交的朋友数
	while(cin >>n && n != 0 )
	{
		friendNum.clear();
		int num;
		for(int i = 0; i < n-1; i++) //主持人不接受数据
		{
			cin >> num;
			friendNum.push_back(num);
		}
		friendNum.push_back(n-1); //将主持人也加以考虑

		while(!friendNum.empty())
		{
			
			sort(friendNum.begin(),friendNum.end(),cmp);
			int t = friendNum[friendNum.size()-1]; //取尾部也就是认识的人最多的数,判断其是否说假话
			
			if(t <= friendNum.size()-1) //是真的
			{
				friendNum.pop_back();
				int j = friendNum.size()-1,k = t;
				while(t--)
				{
					friendNum[j--] -= 1;
				}
			}
			else     //他在骗人
			{
				break;
			}
			eraseZero(friendNum);    //消除没有朋友了的人
		}
		
		if(friendNum.empty()) cout << "true" << endl;
		else cout << "false" << endl;
	}
	return 0;
}

 

 
 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值