用点树 模拟约瑟夫问题
//用点树 模拟约瑟夫问题
//N个人编号:0,1,2, ... N-1, 报数:1到M,报到M的出列
//www.cnblogs.com/flyinghearts
#include<cstdio>
template<int N> struct Round2k {
enum { down = Round2k<N / 2u>::down * 2,
up = down == N ? down : 2 * down };
};
template<> struct Round2k<1> {
enum { down = 1, up = 1};
};
template <int M, typename T = int> //区间[0, M)
class PointTree {
enum { Extra = Round2k<M>::up, N = (M + 1 + Extra) / 2u };
T info[N];
public:
PointTree() { init(); }
void init()
{
info[0] = M; //为了快速初始化数据,实际上放了0到Extra-1共Extra个点
for (int i = Extra / 4u; i < N; ++i) info[i] = 1;
for (int i = 2, k = Extra / 4u; k > 0; k /= 2u, i *= 2)
for (int j = k; j < k * 2; ++j) info[j] = i;
}
int erase_nth(int n)
{
if (n >= info[0]) return -1;
--info[0];
int i = 1;
while (i < Extra) {
if (n < info[i]) { --info[i]; i *= 2; }
else { n -= info[i]; i = i * 2 + 1; }
}
return i - Extra;
}
int count(int n) {
int sum = 0, i = Extra + n;
while (i % 2u) sum += info[(i /= 2u)];
return info[i / 2u] - sum;
}
void show()
{
for (int i = 0; i < M; ++i)
if (count(i)) printf("%2d ", i);
printf("\n");
}
};
int main()
{
const int N = 17; //N个人编号:0,1,2, ... N-1
const int M = 7; //报数:1到M,报到M的出列
PointTree<N, unsigned char> pt;
printf(" total_size: %d bytes\n\n", sizeof(pt));
for (int j = N, k = 0; j >= 1; --j) {
k = (k + M - 1) % j;
int t = pt.erase_nth(k);
printf(" turn: %2d out: %2d rest: ", N - j, t);
pt.show();
}
printf(" \n\n");
}
//N个人编号:0,1,2, ... N-1, 报数:1到M,报到M的出列
//www.cnblogs.com/flyinghearts
#include<cstdio>
template<int N> struct Round2k {
enum { down = Round2k<N / 2u>::down * 2,
up = down == N ? down : 2 * down };
};
template<> struct Round2k<1> {
enum { down = 1, up = 1};
};
template <int M, typename T = int> //区间[0, M)
class PointTree {
enum { Extra = Round2k<M>::up, N = (M + 1 + Extra) / 2u };
T info[N];
public:
PointTree() { init(); }
void init()
{
info[0] = M; //为了快速初始化数据,实际上放了0到Extra-1共Extra个点
for (int i = Extra / 4u; i < N; ++i) info[i] = 1;
for (int i = 2, k = Extra / 4u; k > 0; k /= 2u, i *= 2)
for (int j = k; j < k * 2; ++j) info[j] = i;
}
int erase_nth(int n)
{
if (n >= info[0]) return -1;
--info[0];
int i = 1;
while (i < Extra) {
if (n < info[i]) { --info[i]; i *= 2; }
else { n -= info[i]; i = i * 2 + 1; }
}
return i - Extra;
}
int count(int n) {
int sum = 0, i = Extra + n;
while (i % 2u) sum += info[(i /= 2u)];
return info[i / 2u] - sum;
}
void show()
{
for (int i = 0; i < M; ++i)
if (count(i)) printf("%2d ", i);
printf("\n");
}
};
int main()
{
const int N = 17; //N个人编号:0,1,2, ... N-1
const int M = 7; //报数:1到M,报到M的出列
PointTree<N, unsigned char> pt;
printf(" total_size: %d bytes\n\n", sizeof(pt));
for (int j = N, k = 0; j >= 1; --j) {
k = (k + M - 1) % j;
int t = pt.erase_nth(k);
printf(" turn: %2d out: %2d rest: ", N - j, t);
pt.show();
}
printf(" \n\n");
}
作者: flyinghearts
出处: http://www.cnblogs.com/flyinghearts/
本文采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。