第一次遇到的题目是“猴子选大王”,之后又遇到了几次,索性将我的新手思路记录一下……
题目(最简单版):
n个人围成一圈开始报数,数到m的人出列,下一个人接着从1开始报数,问最后剩下的那个是几号。
近两个月的解答:
第一次:当时刚刚接触编程,不知道怎么让他循环,用的是二维数组。
#include<stdio.h>
void search(int);
int main()
{
int n=6;
search(n);
return 0;
}
void search(int n)
{
int x,y,k=6,i=0,a[6][6];
for(x=0;x<n;x++)
for(y=0;y<n;y++)
a[y][x]=1;//数组为1
for(y=0;y<n&&k>1;y++)
{
for(x=0;x<n;x++)
{
if(a[y][x]!=0)
i++;
if(i==4)
{
for(k=0;k<n;k++)
a[k][x]=0;//逢数到4的列数其元素都为0,此列失去称王机会
i=0;
}
}
k=0;//切记不可放在循环里!
for(x=0;x<n;x++)
{
k=k+a[0][x];//判定是否只剩下一个数
}
}
for(x=0;x<n;x++)
if(a[0][x]==1)
printf("%d",x+1);
}
第二次:看了老师PPT上的解答当时觉得很精彩,但私以为相比于之后的几种思路,这个有点难懂~其实作为初学者,到目前为止每次看书上的解答代码都觉得好精彩……
#include<stdio.h>
int main()
{
int a[7],i,pre,count=0;
for(i=1;i<=6;i++)
a[i]=i+1;//下标对应的元素表示他的下一个人
a[6]=1;
i=6;
while(a[i]!=i)//他的下一个人不是他自己,继续循环
{
pre=i;//a[pre]是i,也是当前的人的号码
i=a[i];//i从1开始
count++;
if(count%4==0)//数到4下去一个
{
a[pre]=a[i];//从此这个号码消失,转变为他的下一个人
i=pre;
}
}
printf("%d",i);
return 0;
}
第三次:刚开始主动接触算法,大概看了眼书然后照猫画虎写了个跟人家不一样的选大王……
#include<iostream>
using namespace std;
bool a[100];//为1时表示已出列
int main()
{
int n,m;
cin>>n>>m;
int count=0,temp=0;//temp记录当前位置
int record=n;//record记录剩下的人数
while(1)
{
while(1)
{
temp++;
if(temp==n+1)
temp=1;
if(a[temp]==0)
break;
}
if(record==1)
break;
count++;
if(count%m==0)
{
a[temp]=1;
record--;
}
}
cout<<temp;
return 0;
}
第四次:书上的解答,思路易懂,比上面我写的好多啦
#include<iostream>
#include<cstring>
using namespace std;
bool a[100];
int main()
{
int n,m,k,temp=0,count=0,person=0;
memset(a,false,sizeof(a));//瞎学归零~
cin>>n>>m;
do
{
temp++;
if(temp==n+1)
temp=1;
if(a[temp]==false)
count++;
if(count==m)//此处不能写为count%m==0,这样的话一旦两个人连着true,person就增加了
{
count=0;
k=temp;
a[temp]=true;
person++;
}
}while(person<n);
cout<<k;
return 0;
}
第五次:看链表时果断还有这题……于是用了个单向循环链表,不过和书上的链表构建方法不太一样,因为之前看《啊哈算法》时被那里介绍的链表写法先入为主了。
#include<iostream>
using namespace std;
struct node
{
int num;
node *next;
};
int main()
{
node *head=NULL,*p,*q;
int n,m,x;
cin>>n>>m;
//建立链表
for(int i=1;i<=n;i++)
{
p=new node;
p->num=i;
if(head==NULL)
head=p;
else
q->next=p;
q=p;
}
q->next=head;//循环上啦
for(int i=1;i<n;i++)
{
for(int j=1;j<m;j++)
{
p=p->next;
}//找到,并弃掉这个结构体
p->next=p->next->next;
}
cout<<p->num;
return 0;
}
第六次:(对这题是真爱~)模拟链表,也是和第二次老师PPT一样用数组值来记录下一个人的序号,但个人觉得更简洁也更好理解一些。
#include<iostream>
using namespace std;
int main()
{
int n,m,a[30];
cin>>n>>m;
for(int i=1;i<n;i++)
a[i]=i+1;
a[n]=1;//循环上啦
int temp=n;
for(int person=0;person<n;person++)//每回合出去一个人直到n人为止
{
for(int k=1;k<m;k++)//用这种写法数到m后,需要出列的人是a[temp]
{
temp=a[temp];
}
cout<<a[temp]<<" ";//这次是输出出列顺序了
a[temp]=a[a[temp]]; //这里就像链表的next指针一样,指向下一个的下一个
}
return 0;
}
对于这道题写到目前这个程度的总结就是:
想个办法让他循环,要么模拟个循环链表,要么让temp(名字随意啦)数到n+1时变成1,然后只要按题目要求照做就好了。