Josephus problem solution with o(n)
1.Description
People are standing in a circle waiting to be executed. Counting begins at a specified point in the circle and proceeds around the circle in a specified direction. After a specified number of people are skipped, the next person is executed. The procedure is repeated with the remaining people, starting with the next person, going in the same direction and skipping the same number of people, until only one person remains, and is freed.
2.Introduction
We have seen this kind of problems before. You can stimulate the whole process to get the answer you want. But its time cost is large, which holds a m*n complexity. This method can be accepted when n and m are accepted small, but fail to handle those situations when n or m is quite large. Thus, today let’s introduce a new method with a complexity of o(n).
3.Dynamic planning
To find the formula to solve this problem, we need to go through several loops to get the inner principle.
Suppose we have n people initially, and the m th person will be executed.
when loop=1, undoubtedly, the (m-1)%n th person will be executed.
when loop=2, let’s see the current situation:
the people list become:
m,m+1,...,n-2,n-1,0,1,2,...,m-2
it will be convenience for us if we map the list above to a new list like this
0,1,2,3,...,n-3,n-2
the map looks like this:
m -> 0
m+1 -> 1
...
...
k-3 -> n-3
k-2 -> n-2
the map here can be summarized as f(x)=(x-m)%n.
Now, let’s define an expression to represent our final answer: f(n,m).Then, it’s common sense that f(1,m)=0. The main problem is to find the relationship between f(1,m) and f(n,m). How can we think?
If we can find the relationship between f(n,m) and f(n-1,m), then we can repeatedly use this relationship to find the relationship between f(n,m) and f(1,m).
As I mentioned above, we use a map from f(n) to f(n-1). Now, we can map it back, then we get what we want:
f(n,m)=(f(n-1,m)+m)%n
Now we can use this formula to get the final answer using a for loop.
4.Code
#include <iostream>
using namespace std;
int main(void){
int n,m;
int answer=0; //we initial answer equals to 0 because for the last f(1,m)=0
cin>>n>>m;
for(int i=1;i<=n;i++){
answer=(answer+m)%i;
}
cout<<answer<<endl;
}
You can see this code is incredible simple but much faster than just stimulating the whole process. And that’s charm of algorithm, I think.
约瑟夫问题:动态规划解决方案

博客介绍了约瑟夫问题的动态规划求解方法,通过分析不同循环次数下的规律,得出公式,并利用该公式通过循环计算出最终答案,提高了效率,避免了m*n的复杂度,展示了算法的魅力。
308

被折叠的 条评论
为什么被折叠?



