算法——The Josephus Problem

題目描述

The problem is named after Flavius Josephus, a Jewish historian who participated in and chronicled the Jewish revolt of 66-70C.E. against the Romans. Josephus, as a general, managed to hold the fortress of Jotapata for 47days, but after the fall of the city he took refuge with 40 diehards in a nearby cave. There the rebels voted to perish rather than surrender. Josephus proposed that each man in turn should dispatch his neighbor, the order to be determined by casting lots. Josephus contrived to draw the last lot, and as one of the two surviving men in the cave, he prevailed upon his intended victim to surrender to the Romans. Your task:computint the position of the survivor when there are initially n people.

輸入

a Positive Integer n is initially people. n< = 50000

輸出

the position of the survivor

樣例輸入

6

樣例輸出

5

代碼

#include<iostream>
using namespace std;
int main(){
	int n;
	cin>>n;
	int s = 0;
	for(int i = 1; i <= n ; i++){
		s = (s + 2)%i;
	}
	cout<<s+1<<endl;
}

算法非常的巧妙,所以看起來很簡單,oj 上是可以通過的哦~
我們再來看一下另一種形式的代碼

#include<iostream>
#include<cstdlib>
using namespace std;
typedef struct{
	int num;
}save;
int Josephus(int n,save *a){ 
	int m = 1;
	save b[50001];
	if(n%2 == 0){
		int k = n/2;
		for(int i = 1;i <= n;i++){
			if(i == 2*k - 1){
				b[m++] = a[i];
			}
		}	
	}
	else{
		int k = n/2;
		for(int i = 1; i <= n; i++)
		if(i == 2*k + 1)
		{
			b[m++] = a[i];
		}
	}
	for( int i = 1; i < m ;i++){
		a[i] = b[i];
	}
	if (m - 1 ==1) {
		return a[m-1].num;
	}
	Josephus(m -1 , a);
} 
int main(){
	int n;
	cin>>n;
	save a[50001];
	for(int i = 1; i <=n ;i++){
		a[i].num = i;
	}
	cout<<Josephus(n,a)<<endl;;
	return 0;
}

在c++環境下運行是沒有問題的,但是有些oj 上通過不了,一直報WrongAnswer,有沒有大佬看看呢?

運行結果

在這裏插入圖片描述
數字太小了,那我們試一下32767(15個1)
在這裏插入圖片描述
運行結果都是一樣的,但是第二種在oj 上通過不了/迷。

思路

第一種方法:
把情況分爲奇數和偶數:
1.首先分析偶數:很容易發現,爲了得到一個人的初始位置,我們只需要將它的新位置乘2並減去1。對倖存者來說,這個關係會保持下去,也就是:J(2k)=2J(k)-1;
2.再來分析奇數:爲了得到新的位置編號相對應的初始位置編號,我們必須把新的位置乘2再加上1,因此,對於奇數我們有J(2k+1)=2J(k)+1;
這是反向替換法;
第二種方法:
在方法一的基礎上進行改進,我們可以得到兩個遞推式的解的一個閉合式,有意思的是,關於閉合式的最優雅的形式涉及規模 n 二進制表示:我們可以對 n 本身做一次向左的循環來得到 J(n)!,例如,J(6)=J(110)2=(101)2=5。
這是前項替換法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章