1012:Joseph

题目

描述

The Joseph's problem is notoriously known. For those who are not familiar with the original problem: from among n people, numbered 1, 2, . . ., n, standing in circle every mth is going to be executed and only the life of the last remaining person will be saved. Joseph was smart enough to choose the position of the last remaining person, thus saving his life to give us the message about the incident. For example when n = 6 and m = 5 then the people will be executed in the order 5, 4, 6, 2, 3 and 1 will be saved.

Suppose that there are k good guys and k bad guys. In the circle the first k are good guys and the last k bad guys. You have to determine such minimal m that all the bad guys will be executed before the first good guy.
 

输入

The input file consists of separate lines containing k. The last line in the input file contains 0. You can suppose that 0 < k < 14.

输出

The output file will consist of separate lines containing m corresponding to k in the input file.

分析

一道很常见的题,思路也不是很难。用一个int型的num来存现存人数,再用一个int型的pos来存当前报数的人的位置,然后就让pos+=m,随后更新num和pos,如果pos<k的话说明好人死了,该m不成立,否则就一直循环下去,如果一直到num==k好人都没死的话,说明这个m符合要求,就可以输出了。

想法很简单,时间复杂度也不是很高,但是当我写完提交的时候却显示tle。刚开始不知道为啥,后面问了别人才知道原来输入的k是会重复的。这样就导致对于一个k会一直从头开始算m,然后时间就会叠的很久。。。

后面就用一个dp数组存结果,先把1到13全算完然后根据输入来输出dp[k],然后就过了,耗时也很短。

代码如下:

#include<iostream>
#include<string>
#include<string.h>
#include<cmath>
#include<queue>
#include<set>
#include<iomanip>
using namespace std;

int k;
int pos;
int num;
bool fail;
int dp[15];

int main() {
	for (int k = 1; k < 14; k++) {
		for (int m = k + 1;; m++) {
			num = 2 * k;//初始有k个好人,k个坏人
			pos = -1;//pos初始化为-1,因为刚开始没有人报数。(注:这里将人从0开始编号,方便取余数)
			fail = false;//判断m是否符合要求
			while (num > k) {//当num==k时,只剩下好人,可以跳出循环
				pos += m;//从pos开始报数到m
				pos %= num;
				if (pos < k) {//如果pos<k,说明死的是好人,不合题意
					fail = true;
					break;
				}
				else {
					num -= 1;//否则杀死坏人
					pos -= 1;//注意要同步更新pos
				}
			}
			if (fail) {
				continue;
			}
			else {
				dp[k] = m;
				break;
			}
		}
	}
	while (cin >> k) {
		if (k == 0) {
			break;
		}
		else {
			cout << dp[k] << endl;
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值