约瑟夫问题
前k个好人和后k个坏人排在一起
要求先删除全部坏人才能删除好人
暴力vector模拟一下。。打表交。。
int ans[15]={-1,2,7,5,30,169,441,1872,7632,1740,93313,459901,1358657,2504881};
以下是暴力模拟。。。答案当然是打表啦。。
//只有 (k+1)的倍数加1或者0 才可能是答案这个结论是推出来的。。很容易推 当删除最后一个坏人时必定有两种情况
1 、 倒数第二个人是在他前面,那么接下来他是 序号1 ,有 m%(k+1)>k 即 m%(k+1)==k+1
所以 m会是k+1的倍数
2、倒数第二个人在他后面,接下来他是序号k+1,从1开始数起,
要满足 (m-1) % (1+k) >k 即 (m-1) % (1+k) ==k+1
所以 m会是k+1的倍数+1
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <list>
#include <vector>
using namespace std;
int n;
int i,j;
int k,h;
int max(int a,int b)
{return a<b?b:a;}
vector <int >sb;
vector <int >::iterator it;
int main()
{
while(cin>>k&&k)
{
int line=0;
int m;
for (i=1;i<=20000000;i++) //随便设置的次数
{
line=!line;
if (!line)
m=i*(k+1)+1; //只有 (k+1)的倍数加1或者0 才可能是答案
else
m=i*(k+1);
if (line) i--;
sb.clear();
for (j=1;j<=k;j++)
sb.push_back(1);
for (j=1;j<=k;j++)
sb.push_back(2);
int kill=0;
int p=0;
while(1)
{
p=(p+m-1)%sb.size(); //暴力模拟
if (sb[p]==2)
{
it=&sb[p];
sb.erase(it);
kill++;
}
else
break;
if (kill==k)break;
}
if (kill==k)
{
printf("%d\n",m);
break;
}
}
}
return 0;
}

本文通过暴力模拟的方式解决了一个特定的约瑟夫问题变种,该问题要求在一定条件下先删除所有标记为“坏人”的元素后才能继续。文中提供了一份C++实现代码,并讨论了可能的答案范围。
1027

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



