1. 程式人生 > >UVa 133 救濟金髮放

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;
}