UVa 133 救济金发放

题意:所有n个人围成一个圈,一边从1号开始逆时针数k个,出局;一边从n号开始顺时针数m个,出局。两个同时发生。如果这两个数到同一个人,就这个人出局。

facing inwards 面朝里; counter 相反地,clockwise 顺时针,counter-clockwise 逆时针

思路:双向循环链表来模拟。按以前书上介绍的实现的,有一个头指针,首尾都指向它。但这里由于要找第k个、第m个,需要进行头指针的判断,所以觉得这里不增加头指针比较好,或者头指针只指向头结点,而头结点和尾结点是互指的,不像这里实现的头结点和尾结点之间还有一个头指针结点。

看很多人用数据模拟实现的。。

注意:if里的相等判断,用==

free同一块内存多次发生未定义错误

指向指针的引用形参的问题。

找不出错误时,可以跑一下别人AC的程序,对比相同输入的输出。

一般发现一组不一致的或错误的数据时,可以试图找到一组尽量简单的错误数据,除非只对该组数据错误。数据越简单,越容易调试。如果只有很大的数据才会出错,通常意味着程序在处理极限数据方面有问题。

#include<stdio.h>
#include<malloc.h>

struct Node
{
 int data;
 Node *next;
 Node *prior;
};

Node* CreateList(Node* &head, int n);
Node* searchk(Node *ptr, Node* &head, int k);
Node* rsearchm(Node *ptr, Node* &head, int m);
void deletenode(Node *ptr);
void show(Node* ptr);

int main()
{
 int n,k,m;
 while(scanf("%d%d%d",&n,&k,&m)==3 && (n||k||m))
 {
  Node *head=NULL;
  Node *mnode=CreateList(head,n); //show(head);
  Node *knode=head->next;
  bool flag=0;
  while(head->next!=head)
  {
   if(flag) printf(",");
   knode=searchk(knode,head,k); //printf("%d\n",knode->data);
   mnode=rsearchm(mnode,head,m);
   bool b=1;//标记最后两个deletenode别重复free
   if(knode!=mnode) printf("%3d%3d",knode->data,mnode->data);
   else { printf("%3d",knode->data); b=0;}
   flag=1;
   Node *sk=knode,*sm=mnode;//下面两句考虑到next位置会不会恰好是要删除的结点
   knode=knode->next; while(knode==sm) knode=knode->next;
   mnode=mnode->prior; while(mnode==sk) mnode=mnode->prior;

   deletenode(sk);
   if(b) deletenode(sm);
  }
  printf("\n");
  free(head);
 }//while
 return 0;
}

void show(Node* ptr)
{
 Node *p=ptr->next;
 while(p!=ptr)
 {
  printf("%d\n",p->data);
  p=p->next;
 }
}

void deletenode(Node *ptr)
{
 if(ptr==NULL) return;
 ptr->prior->next=ptr->next;
 ptr->next->prior=ptr->prior;
 free(ptr);
 ptr=NULL;
}

Node* rsearchm(Node *ptr, Node* &head, int m)
{//逆序移动到当前位置的第m个元素,返回该元素位置
 int i=1;
 Node *p=ptr;
 while(i<m)
 {
  if(p==head) p=p->prior;
  p=p->prior;
  i++;
 }
 if(p==head) p=p->prior;
 return p;/*
 while(p!=head && i<m)
 {
  p=p->prior;
  i++;
 }
 if(p==head) p=p->prior;
 while(i<m)
 {
  p=p->prior;
  i++;
 }
 if(p==head) p=p->prior;
 return p;*/
}

Node* searchk(Node *ptr, Node* &head, int k)
{//顺序移动到当前位置ptr的第k个元素,返回该元素位置 (即数的这k个位置包括当前位置)
 int i=1;
 Node *p=ptr;
 while(i<k)
 {
  if(p==head) p=p->next;  //!!! if里面的==
  p=p->next;
  i++;
 }
 if(p==head) p=p->next;
 return p;
}

Node* CreateList(Node* &head, int n)
{//顺序创建n个结点,head为头指针,next指向头结点;并返回尾结点指针
 head=(Node*)malloc(sizeof(Node));
 head->next=NULL; head->data=0;
 head->prior=NULL;
 Node* ptr=head;
 for(int i=1;i<=n;++i)
 {
  Node* p=(Node*)malloc(sizeof(Node));
  ptr->next=p;
  p->data=i;
  p->next=NULL;
  p->prior=ptr;
  ptr=p;
 }
 //ptr->next=head->next;//n的后一个结点是1
 //head->next->prior=ptr;//1的前一个结点是n
 head->prior=ptr;
 ptr->next=head;//n的后一个结点是头指针
 return ptr;
}

UVa 133 救济金发放

时间: 2024-10-13 07:55:19

UVa 133 救济金发放的相关文章

UVa 133 The Dole Queue

 The Dole Queue  In a serious attempt to downsize (reduce) the dole queue, The New National Green Labour Rhinoceros Party has decided on the following strategy. Every day all dole applicants will be placed in a large circle, facing inwards. Someone i

UVA 133(循环链表)

C - The Dole Queue Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Description  The Dole Queue  In a serious attempt to downsize (reduce) the dole queue, The New National Green Labour Rhinoceros Party has decided

The Dole Queue UVA - 133

In a serious attempt to downsize (reduce) the dole queue, The New National Green Labour Rhinoceros Party has decided on the following strategy. Every day all dole applicants will be placed in a large circle, facing inwards. Someone is arbitrarily cho

算法入门经典-第四章 例题4-3 救济金发放

救济金的问题抽象出来就是几个人围成一个圈坐,给每一个人编号,一个人从1开始,一个人从n开始,从一开始的点到k时,出列一人,n逆时针点人,点到m出列一人.如果我们出列用删除操作,则大大的降低了效率,我们将删除掉的人用0来代替,当我们遇到0时不点人. 使用两个方法来分别逆时针顺时针点人,如果是0,则跳过 n(n<20)个人站成一圈,逆时针编号为1-n.有两个官员,A从1开始逆时针数,B从n开始顺时针数.在每一轮中,官员A数k个就停下来,官员B数m个就停下来(注意有可能两个官员停在同一个人上).接下来

救济金发放(UVa133)

题目具体描述见:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=69 C++11代码如下: 1 #include<iostream> 2 #include<iomanip> 3 using namespace std; 4 int que[25]; 5 int n, k, m; 6 7 int go(int p, i

算法习题---4.3救济金发放(UVa133)

一:题目 (n<20 )个人站成一圈,逆时针编号为1~n.有两个官员,A从1开始逆时针数,B从n开始顺时针数.在每一轮中,官员A数k个就停下来,官员B数m个就停下来(注意有可能两个官员停在同一个人上).接下来被选中的人离开队伍. 输入n,k,m输出每轮被选中的人的编号(如果有两个人,先输出A的)每个输出数字正好占3列. 二:实现思路 A从数组首部向后遍历(若是该位置还有人,则步数加一,否则不改变步数),当遍历到最后,则转回首部继续遍历. B从数组尾部向前遍历(...),若是遍历到首部,则转回尾部

UVA - 133 The Dole Queue(模拟链表)

点击打开链接 n的人围成一个环,然后按逆时针编号1-n,一个人从1开始逆时针数k个数,另一个人从N开始顺时针数m个数,然后 数出来的两个人出列(两个人可能一样)出列,然后继续此过程,直到全部人都出列为止. 思路是用循环链表来模拟,注意 要分情况来讨论. #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #inclu

uva - 133 The Dole Queue(成环状态下的循环走步方法)

类型:循环走步 1 #include <iostream> 2 #include <sstream> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <string> 7 #include <vector> 8 #include <set> 9 #include <cctype> 10 #include &

UVa 133 双向约瑟夫环

背景:1_TlE:没有考虑到,当k,m很大的时候,就会用太多时间,那么我想到了: k=k%n+n;// 之所以要加n,是为了避免,k是n的倍数时,k等于0. m=m%n+n; 2_WA:经过_TLE:之后没有完善,当k不是n的倍数时就不能加n!终究来说还是没有测试所有数据,以后切题,就把所有数据保存在记事本,要全部通过,才提交!! 好多人都说这是一个双向链表的数据结构题,被我数组模拟过了,双向约瑟夫环... 思路:小紫书在这里出这道题,是想让我们锻炼自顶向下的程序框架思想,即:想建立大框架,一些