一道狼人杀笔试题的总结

题目描述:
有n个杀手排成一行,每个杀手都有一个不同的编号编号为1-n),在每个夜晚,杀手都会行动,如果某个杀手编号大于他右边的杀手的编号,他就会杀死他右边的杀手杀手是的行动是瞬间的,因此一个人可能某一个夜晚既杀死了别人又被别人杀死,例如3,2,1这个顺序,在第一个夜晚2会杀死1,同时3也会杀死2显而易见,一段时间之后,就不会有人杀或被杀,平安夜也就到来了,请问在平安夜之前有多少个夜晚。

输入:
输入第一行是一个整数n(1≤n<100000)表示杀手的数量
接下来一行有n个数,是一个1-n的全排列。

输出:
输出包含一个整数,表示平安夜之前经历了多少个夜。

假定有如下100元素的编号={ 22, 24, 69, 13, 53, 29, 83, 12, 51, 5, 70, 3, 97, 59, 9, 11, 41, 28, 64, 57, 27, 25, 38, 93, 36, 73, 23, 50, 86, 95, 49, 26, 74, 0, 96, 65, 10, 67, 18, 66, 37, 92, 54, 1, 88, 34, 46, 58, 45, 82, 87, 2, 43, 62, 90, 85, 75, 63, 14, 19, 16, 35, 78, 47, 98, 21, 44, 40, 99,  4, 42, 15, 8, 6, 60, 31, 94, 80, 81, 55, 30, 61, 32, 20, 89, 77, 56, 71, 7,  17, 68, 48, 33, 52, 72, 39, 84, 79, 76, 91 };

下面分别给出c++和python的代码。

 

c++代码

/*
Author_ZhouJH 
2018/9/8 
*/
#include<iostream>
#include<vector>
using namespace std;
/* 此处为定义的函数,作用是返回一轮迭代后的剩余元素个数,也即生存的人数 */
vector<int> test(vector<int> vec,int number)
{
	vector<int>::iterator it;//迭代器
	vector<int>ll = {vec[0]};//此处表示最左边的那个人永远不会被杀
	for (it = vec.begin(); it != (vec.end() - 1); ++it) //遍历所有的元素
	{
		if (*it < *(it + 1)) //如果右边的元素大于左边的,说明一轮迭代它暂时安全
		{
			//cout << *it;
			//it = vec.erase(it + 1);//删除元素,返回值指向已删除元素的下一个位置  
			ll.push_back(*(it+1));
		}
	}
	cout << "经过第" << number << "次迭代后删除后的值为:\n";
	for (int i = 0; i < ll.size(); i++)
	{
		cout << ll[i] << ",";
	}
	cout << "\n";
	cout << "\n";
	return ll;  //返回值是迭代一轮后生存的元素
}
/* 主函数入口 list向量表示狼人杀的初始编号 */
int main()
{	
	cout << "                      hello! this a c++ example! \n"<<"\n";
	int number = 1;
	//vector<int> list = { 1, 3, 2, 4, 5, 7, 6, 8, 9 };
	vector<int> list = { 22, 24, 69, 13, 53, 29, 83, 12, 51, 5, 70, 3, 97, 
		59, 9, 11, 41, 28, 64, 57, 27, 25, 38, 93, 36, 73, 23, 50, 86, 95, 49, 
		26, 74, 0, 96, 65, 10, 67, 18, 66, 37, 92, 54, 1, 88, 34, 46, 58, 45, 82, 
		87, 2, 43, 62, 90, 85, 75, 63, 14, 19, 16, 35, 78, 47, 98, 21, 44, 40, 99, 
		4, 42, 15, 8, 6, 60, 31, 94, 80, 81, 55, 30, 61, 32, 20, 89, 77, 56, 71, 7, 
		17, 68, 48, 33, 52, 72, 39, 84, 79, 76, 91 };
	cout << "狼人杀的初始编号为:";
	for (int i = 0; i <list.size(); i++)
	{
		cout << list[i] << ",";
	}
	cout << "\n";
	cout << "\n";
	vector<int >a= test(list,number);//调用函数,为第一次迭代后的返回值,可分为有两种情况,一种是直接剩下一个元素(表示游戏结束),否则进入while循环
	while (a.size() != 1)
	{
		number++;
		vector<int >b = test(a,number); //继续调用函数进行迭代
		if (a == b)
		{
			cout << "平安夜经过了"<<number-1<<"天.\n"<<".\n";
			break;
		}
		else
		{
			number++;
			vector<int >hia = test(b, number);
			
			a = hia;
			if (hia == b) //当两次迭代的返回数据一样时,游戏结束!
			{
				cout << "平安夜经过了" << number << "天.\n"<<"\n";
				break;
			}
		}
	}
	return 0;
}

函数输出如下:

 

Python代码

"""
狼人杀Python实现_Zjh
整体思路如下,先按照规则开始杀人,第一波过后可能还有许多人共存,
当程序的两次迭代没有发生变化时,此时程序终止迭代。
"""
#import random
#l=list(range(100)) #100个顺序数
#random.shuffle(l) #打破顺序后的数
l=[22, 24, 69, 13, 53, 29, 83, 12, 51, 5, 70, 3, 97,
59, 9, 11, 41, 28, 64, 57, 27, 25, 38, 93, 36, 73,
23, 50, 86, 95, 49,26, 74, 0, 96, 65, 10, 67, 18, 66, 37,
92, 54, 1, 88, 34, 46, 58, 45, 82,87, 2, 43,62, 90, 85, 75,
63, 14, 19, 16, 35, 78, 47, 98, 21, 44, 40, 99,4, 42, 15, 8,
6, 60, 31, 94, 80, 81, 55, 30, 61, 32, 20, 89, 77,
 56, 71, 7,17, 68, 48, 33, 52, 72, 39, 84, 79, 76, 91]
def test(s):
    s1 = [s[0]]
    for x in range(len(s) - 1):
        if s[x] < s[x + 1]:
            s1.append(s[x+1])
    return s1
def main():
    #第一次迭代,i表示迭代的次数,初始化为1,也即最小的平安夜为1
    i=1
    s=test(l)
    print('第{}次迭代后={}'.format(i, s))
    #当s列表的长度为1,也即第一次迭代后就剩下一个元素了,此时停止,也即平安夜的天数为1
    while len(s) != 1:
        i = i + 1
        a=test(s)
        print('第{}次迭代后={}'.format(i,a))
        if a==s:
            i=i-1
            break
        else:
            #print('i=%s'%i)
            b=test(a)
            s = b
            if a==b:
                i=i-1
                break
            else:
                i = i + 1
                print('第{}次迭代后={}'.format(i, b))
    return i
print('原始序号为=%s'%l)
number=main()
print('平安夜所需的日子为:%s'%number)

 

在pycharm中运行的结果:

程序仅供参考,如有问题可留言交流!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值