详解约瑟夫问题 dp

使用链表的方式这里就不进行介绍了,这里主要介绍的是dp方式的解决,重点在于公式的讲解。

 

假设我们现在有n个人,那么这了n个人杀掉一个人之后,就变成了一个n-1个人的问题了,这就是一个子问题,dp的思想就应该出来了,那么要如何找到n个人的问题和n-1个人的问题之间的关联呢?

现在有n个人,我们从第一个人开始数,直到数到第k个人,那么数到的第k个人就被删除了。剩下了n-1个人,然后又重复进行这个过程,n-1个人的问题就相当于我们n个人的问题去掉第k个人然后从第k-1个人开始杀,所以n-1问题就是n个人问题去掉一个人之后,开始位置变成k+1后的一个问题,最终n-1问题的剩下的那个人的位置,找到其在n问题中的对应位置就可以了。

图示是一个5个人,k等于2的问题

用图来表示就是上面这个样子,图中画线的部分就是表示这个人在当前n个人的时候他会首先被删除,然后以k+1位置从头开始就变成n-1个人的问题,然后n-1问题又删除一个人不断循环直到最后只剩一个人,其实这个过程中剩下的那个人的位置在原来5个人的位置的时候一直都没有变化,都是3位置,只是在4个人问题的时候其变成了1位置,3个人的问题的时候其变成了3位置,所以我们只要找到了这种不同子问题的位置的变化关系就可以知道答案了。

 

代码实现

public static void main(String[] args) {
	Scanner input = new Scanner(System.in);
	int n = input.nextInt();
	int k = input.nextInt();
	int[] dp = new int[n + 1];
	dp[1] = 1;
	for (int i = 2; i <= n; i++) {
        // dp的核心公式,dp[i]剩下的那个人就等于dp[i-1]剩下的那个人变换以下位置
		dp[i] = (dp[i - 1] + k - 1) % i + 1;
	}
	System.out.println(dp[n]);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值