Joseph
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1303 Accepted Submission(s):
799
Suppose that there are k good guys and k bad guys. In the circle the first k are good guys and the last k bad guys. You have to determine such minimal m that all the bad guys will be executed before the first good guy.
代码:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#define len sizeof(struct line)
typedef struct line //构成链表的结点
{
int data;
struct line *next;
}list;
int visit[30]; //用于标记坏人是否被杀
list*creat(int k) //建立循环链表
{
int n;
list*p1,*p2,*head=NULL;
for(n=1; n<=2*k; n++)
{
p1=(list *)malloc(len);
p1->data=n;
if(n==1)
head=p2=p1;
else
p2->next=p1;
p2=p1;
}
p2->next=head;
return head;
}
int countnum(int k,int m,list*head)
{
int count=0,num,kill; //count用于统计被杀的人的数量,num作为每个周期的计数器,kill作为每次杀人之后,将剩下的人重新编号后的将要被杀的那个人的编号
list *p=head;
memset(visit,0,sizeof(visit)); //每次都要初始化
while(count<k) //当被杀的人的数量==k的时候,恰好所有的坏人被杀,所有的好人都活着
{
num=1; //计数时每次都要从1开始
kill=m%(2*k-count); //计算每次杀人之后,将剩下的人重新编号后,将要被杀的那个人的编号
if(kill==0) //如果剩下的人的数量恰好能被m整除,说明此时m>=剩下的人的数量了,那么将要被杀的人的编号就是最后一人
kill=2*k-count;
while(visit[p->data]!=0) //用于跳过曾经被杀的人,不计数在内
{
p=p->next;
}
while(num<kill) //找到将要被杀的那个人
{
p=p->next;
if(visit[p->data]==0)
num++;
}
if(p->data<=k&&p->data>=1) //如果将要被杀的人的是好人,则失败,说明此周期k不合适
break;
if(p->data>k&&p->data<=2*k) //如果如果将要被杀的人的是坏人,则将将要被杀的人标记为被杀,被杀的人的数量加1
{
visit[p->data]=1;
count++;
}
p=p->next; //到下一个结点
}
return count; //返回被杀的人的数量
}
int main()
{
int n,i,k,j,a[16],m,t;
list *p1,*p2,*head;
for(k=1;k<14;k++) //打表,避免超时
{
head=creat(k); //建立链表
if(k<=9) //当k<=9的时候,周期j并没有超过2000
{
for(j=k+1;;j++)
{
t=countnum(k,j,head);
if(t==k)
break;
}
}
else
{
for(j=90000;;j++) //当k>9的时候,周期j已经超过了90000,所以从90000开始,避免超时
{
t=countnum(k,j,head);
if(t==k)
break;
}
}
a[k]=j; //一旦找到合适的周期,将其存入数组中
}
while(~scanf("%d",&k)&&k)
{
printf("%d
",a[k]);
}
}