首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

100分求一算法解决办法

2012-01-02 
100分求一算法杀人游戏N个人坐成一圈玩杀人游戏,按顺时针编号1234......从1号开始顺时针开始数到第m号就杀

100分求一算法
杀人游戏
N个人坐成一圈玩杀人游戏,按顺时针编号   1   2   3   4   ...   ...    
从1号开始顺时针开始数到第m号就杀掉第一个人,被杀掉的人要退出游戏。    
如果数到了编号的末尾,就逆时针方向继续数,如果又数到了编号的开头,就恢复顺时针继续。    
重复,直至杀掉所有人,当剩下最后一个人时,游戏结束,聪明的你能告诉我活到最后的幸存者最初的编号是多少吗?

输入数据:N、M

输出数据:幸存者的编号  

考核标准:技术语言不限,程序输出结果必须正确,内存使用越少越好,程序的执行时间越快越好。




[解决办法]
另类杀人游戏


周末的晚上,百度的员工们总喜欢聚集在公司的会议室玩杀人游戏。从1警1匪到n警n匪,他们尝试了几乎所有流行的杀人游戏规则。终于有一天,连最热衷杀人游戏,“杀人”不眨眼的Austin也开始对无休止的辩论感到厌烦。于是,他决定改变他的一贯作风,他开始变成了一个“杀人不睁眼”的杀手。


如何做到杀人不睁眼呢?Austin早已构思好他的杀人计划:

1. N个人(包括Austin)坐成一圈玩杀人游戏,按顺时针编号1,2,3,4。。。。。

2. Austin从1号开始顺时针开始数到第m号就杀掉第一个人。被杀掉的人要退出游戏。

3. 如果第m个人恰好是Austin自己,他就杀掉他顺时针方向的下一个人。

4. Austin从被杀的人的下一个顺时针数m个人,把第m个杀掉。

5. 重复2-4,直至杀掉所有人。


Austin把这个杀人计谋告诉了法官小k,他便可以闭起眼睛杀人啦。作为一个正直善良的法官,小k当然不能让残忍的Austin得逞,于是,她偷偷把Austin的杀人计划告诉了作为警察的你,聪明的百度之星。现在,你的任务是活到最后,与Austin单挑。


输入:

第一个行包含一个整数T,表示有T组测试数据。


对于每组测试数据:

三个整数

N,M,T,(3 <=N <=10000,1 <=M,T <=10000) 分别表示参与游戏的人数,Austin每隔M个人会杀掉一人,Austin初始位置的标号。


输出:

每个测数数据输出一个整数。

你需要选择的初始位置的序号,以确保最后剩下的两个人是你与Austin。


输入例子:

2

7 4 1

7 4 1


输出例子

5

5


例子说明:杀人顺序为4 2 7 6 3 5 , 所以5 是你要选择的位置。

[解决办法]
难度不大咯~!但是还是写了半小时:)

using System;
using System.Collections.Generic;
using System.Text;

namespace 杀人者游戏
{
class Program
{
static void Main(string[] args)
{
/*杀人游戏N个人坐成一圈玩杀人游戏,按顺时针编号 1 2 3 4 ... ...
*
* 从1号开始顺时针开始数到第m号就杀掉第一个人,被杀掉的人要退出游戏。
*
* 如果数到了编号的末尾,就逆时针方向继续数,如果又数到了编号的开头,就恢复顺时针继续。
*
* 重复,直至杀掉所有人,当剩下最后一个人时,游戏结束,
*
* 聪明的你能告诉我活到最后的幸存者最初的编号是多少吗?

输入数据:N、M

输出数据:幸存者的编号 */


int N = Convert.ToInt16(Console.ReadLine()); //N

bool [] p=new bool [N]; //建立一个BOOL数组,如果为FALSE,则证明此位的人存活,否则则以.

bool fx = false; //判断逆时针还是顺时针;

int M = Convert.ToInt16(Console.ReadLine());

int num = 1;//记录指针
int js = 1;//总计数,一下循环运行多少次

while (true)
{
if (isok(p))//如果OK
{
if (js % M == 0 && !p[num - 1])
{
p[num - 1] = true;
Console.WriteLine( "本次出圈人编号: " + (num - 1).ToString());
}
if (num == N || num == 1) fx = !fx;
if (fx)
{

num++;
while (p[num - 1] && num < N)
{
num++;
}
js++;
}
else
{
num--;
while (p[num - 1] && num> 1)
{
num--;
}
js++;


}
}
else break;
}
for (int i = 0; i < p.Length; i++) //判断最后剩余的是谁
{
if (!p[i])
{
Console.WriteLine( "最后胜利者编号: "+i.ToString());
break;
}
}

Console.ReadLine();


}
static bool isok(bool[] a) //判断是否只剩余1个人的方法,若成立,则证明存活人数> 2,则需要继续
{
bool cf = false;
for (int i = 0; i < a.Length; i++)
{
if (!a[i])
{
if (cf)
{
return true;
}
cf = true;

}
}
return false;
}
}
}


//测试通过

15
5
本次出圈人编号:4
本次出圈人编号:9
本次出圈人编号:14
本次出圈人编号:8
本次出圈人编号:2
本次出圈人编号:5
本次出圈人编号:12
本次出圈人编号:10
本次出圈人编号:0
本次出圈人编号:11
本次出圈人编号:6
本次出圈人编号:3
本次出圈人编号:7
本次出圈人编号:13
最后胜利者编号:1


[解决办法]
楼上的明显错了啊
14出圈了
接下来的就应该是10出圈的吧
其实这个算法不算难的
我C++当时学得不是很好,指针都有点忘记了
不过算法当时大学里学得还不错
后来就直接学了C#了
楼主可以自己先分析一下
你也说了不管那种语言,那你可以用自己最原始的语言先整理一下
先自己举几个数字,然后得出结论
算法最重要的还是自己推一下

[解决办法]
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication51
{
class Program
{
static int KillGame(int n, int m)
{
//建立一个n位每个元素都为1的数组
int[] nums = new int[n];
for (int i = 0; i < nums.Length; i++)
nums[i] = 1;
//索引初始化为0,计数初始化为0,折返标志
int index = 0, count = 0, flag = 1;
//直到数组里只剩下一个1(即第一个1的索引位置和最后一个相同)
while (Array.IndexOf(nums, 1) != Array.LastIndexOf(nums, 1))
{
//如果索引位置是1,则计数+1
if (nums[index] == 1)
{
count++;
}
//根据标志,前进或者向后退一格
index += flag;
//如果计数等于m时,此人被踢出,此位置变成0,计数器清0
if (count == m)
{
Console.WriteLine( "本次出圈人编号:{0} ", index - flag + 1);
nums[index - flag] = 0;
count = 0;
}
//如果索引到头,将索引设置为正数第二位,并更改标志
if (index == -1)
{
index = 1;
flag = -flag;
}
//如果索引到末尾,将索引设置为倒数第二位,并更改标志
if (index == nums.Length)
{
index = nums.Length - 2;
flag = -flag;
}
}
return Array.IndexOf(nums, 1) + 1;
}
static void Main(string[] args)
{
Console.WriteLine( "\n幸存者的编号是:{0} ", KillGame(7, 3));
}
}
}

//n = 7, m = 3 测试结果:

本次出圈人编号:3
本次出圈人编号:6
本次出圈人编号:4
本次出圈人编号:2
本次出圈人编号:5
本次出圈人编号:1

幸存者的编号是:7
请按任意键继续...

//n = 15, m = 5 测试结果:



本次出圈人编号:5
本次出圈人编号:10
本次出圈人编号:15
本次出圈人编号:9
本次出圈人编号:3
本次出圈人编号:6
本次出圈人编号:13
本次出圈人编号:8
本次出圈人编号:2
本次出圈人编号:14
本次出圈人编号:1
本次出圈人编号:12
本次出圈人编号:7
本次出圈人编号:11

幸存者的编号是:4
请按任意键结贴...

[解决办法]
nattystyle(霹雳冰).

15,5 的,你后面代码才是错误的,一开始我疏忽,的确所有数字都少1,但是结果是正确的.


using System;
using System.Collections.Generic;
using System.Text;

namespace 杀人者游戏
{
class Program
{
static void Main(string[] args)
{
/*杀人游戏N个人坐成一圈玩杀人游戏,按顺时针编号 1 2 3 4 ... ...
*
* 从1号开始顺时针开始数到第m号就杀掉第一个人,被杀掉的人要退出游戏。
*
* 如果数到了编号的末尾,就逆时针方向继续数,如果又数到了编号的开头,就恢复顺时针继续。
*
* 重复,直至杀掉所有人,当剩下最后一个人时,游戏结束,
*
* 聪明的你能告诉我活到最后的幸存者最初的编号是多少吗?

输入数据:N、M

输出数据:幸存者的编号 */


int N = Convert.ToInt16(Console.ReadLine()); //N

bool [] p=new bool [N]; //建立一个BOOL数组,如果为FALSE,则证明此位的人存活,否则则以.

bool fx = false; //判断逆时针还是顺时针;

int M = Convert.ToInt16(Console.ReadLine());

int num = 1;//记录指针
int js = 1;//总计数,一下循环运行多少次

while (true)
{
if (isok(p))//如果OK
{
if (js % M == 0 )
{
p[num - 1] = true;
Console.WriteLine( "本次出圈人编号: " + num.ToString());
}
if (num == N || num == 1) fx = !fx;
if (fx)
{

num++;
while (p[num - 1] && num < N)
{
num++;
}
js++;
}
else
{
num--;
while (p[num-1] && num> 1)
{
num--;
}
js++;
}
}
else break;
}
for (int i = 0; i < p.Length; i++) //判断最后剩余的是谁
{
if (!p[i])
{
Console.WriteLine( "最后胜利者编号: "+(i+1).ToString());
break;
}
}

Console.ReadLine();


}
static bool isok(bool[] a) //判断是否只剩余1个人的方法,若成立,则证明存活人数> 2,则需要继续
{
bool cf = false;
for (int i = 0; i < a.Length; i++)
{
if (!a[i])
{
if (cf)
{
return true;
}
cf = true;

}
}
return false;
}
}
}


15
5
本次出圈人编号:5
本次出圈人编号:10
本次出圈人编号:15
本次出圈人编号:9
本次出圈人编号:3
本次出圈人编号:6
本次出圈人编号:13
本次出圈人编号:11
本次出圈人编号:1
本次出圈人编号:12
本次出圈人编号:7
本次出圈人编号:4
本次出圈人编号:8
本次出圈人编号:15


本次出圈人编号:14
最后胜利者编号:2

[解决办法]
抱歉,nattystyle(霹雳冰) 也是正确的!

using System;
using System.Collections.Generic;
using System.Text;

namespace 杀人者游戏
{
class Program
{
static void Main(string[] args)
{
/*杀人游戏N个人坐成一圈玩杀人游戏,按顺时针编号 1 2 3 4 ... ...
*
* 从1号开始顺时针开始数到第m号就杀掉第一个人,被杀掉的人要退出游戏。
*
* 如果数到了编号的末尾,就逆时针方向继续数,如果又数到了编号的开头,就恢复顺时针继续。
*
* 重复,直至杀掉所有人,当剩下最后一个人时,游戏结束,
*
* 聪明的你能告诉我活到最后的幸存者最初的编号是多少吗?

输入数据:N、M

输出数据:幸存者的编号 */


int N = Convert.ToInt16(Console.ReadLine()); //N

bool [] p=new bool [N]; //建立一个BOOL数组,如果为FALSE,则证明此位的人存活,否则则以.

bool fx = false; //判断逆时针还是顺时针;

int M = Convert.ToInt16(Console.ReadLine());

int num = 1;//记录指针
int js = 1;//总计数,一下循环运行多少次

while (true)
{
if (isok(p))//如果OK
{
if (js % M == 0)
{
p[num - 1] = true;
Console.WriteLine( "本次出圈人编号: " + num.ToString());
}
if (num == N || num == 1) fx = !fx;
if (fx)
{
while (true)
{
// if(num[
num++;
if (!p[num - 1]) break;
if (num == N)
{
num++;
while (true)
{
num--;
if (!p[num - 1])
{
fx = !fx;
goto start;
}

}
}
}
}
else
{
while (true)
{
num--;
if (!p[num - 1]) break;
if (num == 1)
{
num--;
while (true)
{
num++;
if (!p[num - 1])
{
fx = !fx;
goto start;
}

}
}

}
}
start: ;
js++;

}
else break;
}
for (int i = 0; i < p.Length; i++) //判断最后剩余的是谁
{
if (!p[i])
{
Console.WriteLine( "最后胜利者编号: "+(i+1).ToString());
break;
}


}

Console.ReadLine();


}
static bool isok(bool[] a) //判断是否只剩余1个人的方法,若成立,则证明存活人数> 2,则需要继续
{
bool cf = false;
for (int i = 0; i < a.Length; i++)
{
if (!a[i])
{
if (cf)
{
return true;
}
cf = true;

}
}
return false;
}
}
}


15
5
本次出圈人编号:5
本次出圈人编号:10
本次出圈人编号:15
本次出圈人编号:9
本次出圈人编号:3
本次出圈人编号:6
本次出圈人编号:13
本次出圈人编号:8
本次出圈人编号:2
本次出圈人编号:14
本次出圈人编号:1
本次出圈人编号:12
本次出圈人编号:7
本次出圈人编号:11
最后胜利者编号:4
[解决办法]
我也来写一个,
public int GetLast(int MembersCount,int TotailSound)
{
int[, ] Members = new int[MembersCount,2];//二维数组,用于记录前,后报数的人的位置
int Rest = MembersCount;///记录剩余人数
int NextIndex = 0;//下一位报数的人
int LastIndex =0;//上一位报数的人
int CurrentIndex=0;//当前报数的人
int SoundNum = 0;//当前进行的报数
int Direction = 0;//报数方向,0为顺时针方向,1为逆时针方向
for(int i = 0 ;i <MembersCount;i++)//生成二维数组,位置1的上一个报数的位置为MembersCount-1,位置MembersCount-1的下一位为1。
{
if(i==MembersCount-1)
Members[i, 0] = 0;
else
Members[i,0]=i + 1;
if(i==0)
Members[i, 1] = MembersCount - 1;
else
Members[i, 1]=i - 1;
}
while(Rest> 1)
{
SoundNum += 1;//报数+1
NextIndex = Members[CurrentIndex, 0];
LastIndex = Members[CurrentIndex, 1];
if(SoundNum==TotailSound)//如果报数为指定TotailSound
{
//当前报数的人出圈,并让出报数的顺序
Members[LastIndex, 0] = NextIndex;
Members[NextIndex, 1] = LastIndex;
Rest -= 1;
SoundNum = 0;//准备下一轮报数
Console.WriteLine( "Out:{0} " , new object[] {CurrentIndex + 1});
}
//判断报数方向
if( CurrentIndex < LastIndex && CurrentIndex < NextIndex)
Direction = 0;
else if( CurrentIndex > LastIndex && CurrentIndex > NextIndex)
Direction = 1;
CurrentIndex = Members[CurrentIndex, Direction];//下一位将要报数的人;
}
return CurrentIndex +1;
}

试验结果:
GetLast(15,5);
Out:5
Out:10
Out:15
Out:9
Out:3
Out:6
Out:13
Out:7
Out:4
Out:12
Out:2
Out:8
Out:1
Out:11
14胜出
GetLast(7,4);
Out:4
Out:6
Out:1
Out:7
Out:3
Out:2
5胜出
[解决办法]
using System;
using System.Collections;

namespace ConsoleApplication1
{
/// <summary>
/// Class1 的摘要说明。
/// </summary>
class Class1
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
int L = int.Parse( Console.ReadLine() );

int M = int.Parse( Console.ReadLine() );
ArrayList Peoples = new ArrayList();
for(int i =0;i <L;i++)
{
Peoples.Add(new People(i+1));
}

//周期描述
//正方向周期为 1 ~ N-1
//反方向周期为 N~2

int Index =1;//指针当前位置
bool Direction=true;//查找方向
while( Peoples.Count> 1)
{
int tmp = M;
//修正查找位置 始终为当前方向上的第一个位置
tmp += Index-1;
Index= 1;


int Cyc = Peoples.Count-1;//周期长度为总人数 - 1
int C= tmp/Cyc;//转弯次数
Index = tmp%Cyc;//转弯后的偏移量
if( Index == 0)
{
C--;
Index = Cyc;
}
//求新方向
if( C % 2 !=0)
{
Direction = !Direction;
}
//根据方向和偏移量计算坐标
int x;
if(Direction)
{
x= Index-1;
}
else
{
x=Peoples.Count - Index;
}
Console.WriteLine( ((People)Peoples[x]).Index);
Peoples.RemoveAt(x);
}
//幸存者
if(Peoples.Count> 0)
{
Console.WriteLine( ((People)Peoples[0]).Index);
Peoples.RemoveAt(0);
}
Console.ReadLine();
}
}

class People
{
public People(int Index)
{
this.Index = Index;
}
public int Index;
}
}

[解决办法]
这个用链表实现是很简单的,但是写起来可能代码比较多
用c#写格简单的
public string KillGame(int N,int M)
{
int flag=0;
bool clockwise=false;
bool[] people=new bool[N];
int i=1;
int k=0;
string Return= " ";
for(;;)
{

if(flag==0||flag==N-1) clockwise=!clockwise;
if(clockwise)
{
if(people[flag]!=true) i++;
flag++;

}
else
{
if(people[flag]!=true) i++;
flag--;

}
if(i==M)
{
people[flag]=true;
k++;
Return+=flag.ToString()+ " ";
i=0;
}
if(k==N-1) break;

}
return Return+ " "+flag.ToString();
}
[解决办法]
wdzr_826(玉面斗鸡眼)

我发现你的代码有一个问题:
if(i==M)
{
people[flag]=true;
k++;
Return+=flag.ToString()+ " ";
i=0;
}
你最后把i=0了.这个并没有反向报数,而是到最后一位之后返回到第一位报数,而应该是到最后一位之后,报数指针返回倒数第二位,你觉得呢
[解决办法]
楼主的要求是 "内存使用越少越好,程序的执行时间越快越好 "。楼上的结果是正确的,但好象在执行时间尽量少这个要求没有体现出来
1、每轮报数都需要对是否已出圈进行判断,这样每循环一圈都需要相同的次数,而定位出圈位置的效率会越来越低。
2、方法中多次使用了Array.Indexof,Array.LastIndexof方法,这相当于在原始人数中进行了多次循环,会消耗大量时间.
用类似于链表的方式处理可以避免类似的问题,每轮报数可跳过已出圈的位置进行有效定位,这样可保证每轮报数定位出圈位置的效率不变,(比较符合现实情况).
人数人的情况下体现不出差别,可以通过人数123456,报数长度7来试验两种方法的时间差别
[解决办法]
偶的算法不能满足要求么?
不用遍历任何节点
循环只要执行 N-1次 即能得到结果

第一次算的时候 N个人 正方向 从第1个人 数到M
根据这些数据很容易能求出,要杀的人的位置(索引) 和方向
根据周期N-1求 M/(N-1)=整周期数, M%(N-1)=偏移量
杀掉算出的索引位置处的人 (RemoveAt)
第 K+1 次杀的时候 N-K个人 X方向 从第i(上次杀的人的位置)个人 数到M
将索引定在当前方向的第1个人,那么要多数 索引位置到当前方向第一个人的中间人的个数
也就是
第 K+1 次杀的时候 N-K个人 X方向 从第 1 个人 数到M +i-1
(这个跟初始位置的情况一样,以此类推.....)

[解决办法]
[CODE]/**
@ Content:杀人游戏之递归算法LAV版
@ Author :Eastsun
@ Version:1.0
*/
#define MAX_N 1000
#define MAX_LEN 8
int solve(int n,int m,int k){
int killer[MAX_N+1];
int index,temp,result;
m--; k--;
killer[n] =k;
for(index =n-1;index> =3;index--)
if((temp=m%(index+1))==killer[index+1])killer[index] =index -1;
else killer[index] =(killer[index+1]+index-temp)%(index+1);
if(killer[3]==m%3) result =(killer[3]+2)%3;
else result =3-killer[3]-m%3;
for(index =4;index <=n;index++)


if(killer[index]==m%index) result =(result+m+2)%index;
else result =(result+m+1)%index;
return result+1;
}
long getNum(int x,int y,int max){//取得一个不大于max的正数
char numKey[11];
char buf[MAX_LEN+2],key;
long num,n,k;
strcpy(numKey, "0bnmghjtyu ");
buf[MAX_LEN+1] =0;
n =num =0;
while(1){
memset(buf+n, ' ',MAX_LEN+1-n);
buf[n] = '_ ';
TextOut(x,y,buf,0x41);
key =getchar();
if(key==0x0d){
TextOut(x+n*6,y, " ",0x41);
return num;
}
if(key==0x1b){
TextOut(x+n*6,y, " ",0x41);
return -1;
}
if(key==23&&n> 0){
n--;
num =num/10;
}
else{
for(k=0;k <10&&numKey[k]!=key;k++);
if(k> =10||n> =MAX_LEN||num*10+k> max) continue;
buf[n++]=k+ '0 ';
num =num*10+k;
}
}
}
void main(){
int n,m,k;
char text[20];
while(1){
ClearScreen();
Refresh();
TextOut(2,1, "Input N(2 <N <1001): ",0x41);
if((n=getNum(110,1,1000)) <3) break;
TextOut(2,15, "Input M(0 <M): ",0x41);
if((m=getNum(80,15,0x7fff)) <=0) break;
TextOut(2,29, "Input K(0 <K <=N): ",0x41);
if((k=getNum(98,29,n)) <=0) break;
sprintf(text, "Position :%d ",solve(n,m,k));
TextOut(8,43,text,0x41);
if(getchar()==0x1b) break;
}
}
[/CODE]

[解决办法]
第二种算法,单链表方式,循环次数小于N*(N-1),大于2*N*M
Private Function GetLastB(ByVal Count As Integer, ByVal M As Integer) As Integer
Dim Members(Count - 1) As Integer
Dim re As Integer
For i As Integer = 0 To Count - 1
Members(i) = i + 1
Next
Dim mCount As Integer = 0
Dim flag As Integer = 1
Dim currentindex As Integer
While True
If Members(currentindex) <> 0 Then
mCount += 1
If mCount = M Then
Console.WriteLine( "out: " & Members(currentindex))
Members(currentindex) = 0
mCount = 0
re += 1
End If
End If
currentindex += flag
If currentindex = -1 Then
flag = 1
currentindex = 1
If Members(0) = 0 And mCount > 0 Then
mCount -= 1
End If
ElseIf currentindex = Count Then
flag = -1
currentindex = Count - 2
If Members(Count - 1) = 0 And mCount > 0 Then
mCount -= 1
End If
End If
If re = Count - 1 And Members(currentindex) <> 0 Then
Exit While
End If
End While
Return Members(currentindex)
End Function

[解决办法]
刚学.net。不会用 Javascript 做了一个 请指教

<HTML>
<HEAD>
<TITLE> JavaScript </TITLE>
<SCRIPT LANGUAGE= "JAVASCRIPT " TYPE= "TEXT/JAVASCRIPT ">
<!--
var n = prompt( "Number of people ", "Type your number here ");
var m = prompt( "Killing Number ", "Type your number here ");

var people = new Array();
var count,flag=1;
for (count = 1; count <= n; count++)
{
people[count] = new Array();
people[count][1]=1;
}

count=0;
var h=0;


//alert( "eliot1 "+flag);

for (; count <n-1; )
{
if (flag==1)
{
if(h==0)
var j=0;
else
var j=h-1;

for (var i=1; i <=n; i++)
{

if (people[i][1]==1)
{
j++;
if (j==m&&count <n)
{
people[i][1]=0; //people get killed
count++;
j=0;
}
}

}
flag=-1;
}

if (flag==-1)
{
if(j==0)
h=0;
else
var h=j-1;
for (var i=n; i> 0; i--)
{
if (people[i][1]==1)
{
h++;
if (h==m&&count <n)
{
people[i][1]=0; //people get killed
count++;
h=0;

}

}

}

flag=1;
}
}

for (count = 1; count <= n; count++)
{

if(people[count][1]==1)

alert( "Surviver is "+count);
}


//-->
</script>
</HEAD>
<BODY>


</BODY>
</HTML>

[解决办法]
/*
* Greenery 2007-07-14
杀人游戏
N个人坐成一圈玩杀人游戏,按顺时针编号 1 2 3 4 ... ...
从1号开始顺时针开始数到第m号就杀掉第一个人,被杀掉的人要退出游戏。
如果数到了编号的末尾,就逆时针indicator继续数,如果又数到了编号的开头,就恢复顺时针继续。
重复,直至杀掉所有人,当剩下最后一个人时,游戏结束,聪明的你能告诉我活到最后的幸存者最初的编号是多少吗?

输入数据:N、M

输出数据:幸存者的编号
*/


using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace 杀人游戏
{
class Program
{
static void Main(string[] args)
{
try
{
int n = int.Parse(args[0]);
int m = int.Parse(args[1]);
Game game = new Game(n, m);
game.Play();
//Console.ReadKey();
}
catch (Exception ex)
{

Console.Write(ex.Message);
}
}
}


class Game
{
/// <summary>
/// 游戏人数
/// </summary>
int m_nGamePlayers;

/// <summary>
/// 间隔数
/// </summary>
int m_nNumber;

/// <summary>
/// 游戏参与者列表
/// </summary>
List <int> m_players;

public Game(int n, int m)
{
if (n < 2 || m < 2)
{
throw new ArgumentOutOfRangeException( "m,n必须大于2 ");
}
m_nGamePlayers = n;
m_nNumber = m;
}

/// <summary>
/// 游戏主体
/// </summary>
/// <returns> </returns>
public int Play()
{
DateTime startTime = DateTime.Now;
// 数组索引
int index = 0;
// 杀人的计数器
int counter = 0;
// 方向
bool indicator = true;

Init();

// 游戏控制,人数大于1将继续游戏
while (m_players.Count > 1)
{
counter++;
//Console.Write(string.Format( "m_players.Count={0}, indicator={1}, player={2}, counter={3} ", m_players.Count, indicator, m_players[index], counter));


if (counter == m_nNumber) // 当读到当前游戏者为指定的杀人数字时,杀。。。
{
counter = 0;
Console.WriteLine(string.Format( "--> 杀掉{0} ", m_players[index]));
m_players.RemoveAt(index);

// 杀人后的数据修正
// 如果是杀了最后一个,指针要退回一个
if (index > m_players.Count - 1)
index = m_players.Count - 1;
else if (index == 0) // 如果杀了第一个,方向改为向前
indicator = true;
else if (!indicator) // 当饭方向杀人时,下一个人的指针要想前移动
index--;
}
else
{
// 计算方向
if (index > = m_players.Count - 1)
indicator = false;
else if (index == 0)
indicator = true;

// 数数
if (indicator)
index++;
else
index--;
}
}
Console.WriteLine(string.Format( "最后胜利者:{0}, 游戏耗时:{1} ", m_players[0], (DateTime.Now-startTime)));
return m_players[0];
}

/// <summary>
/// 游戏初始化
/// </summary>
private void Init()
{
Console.WriteLine(string.Format( "游戏人数:{0}, 计数:{1} ", m_nGamePlayers, m_nNumber));
m_players = new List <int> (m_nGamePlayers);
for (int i = 0; i < m_nGamePlayers; i++)
{
m_players.Add(i + 1);
}
}
}
}
--------------
游戏人数:17, 计数:4
--> 杀掉4
--> 杀掉8
--> 杀掉12
--> 杀掉16
--> 杀掉13
--> 杀掉7
--> 杀掉2
--> 杀掉6
--> 杀掉14
--> 杀掉11
--> 杀掉3
--> 杀掉10
--> 杀掉9
--> 杀掉15
--> 杀掉5
--> 杀掉1
最后胜利者:17, 游戏耗时:00:00:00.0156250

热点排行