设有N个人围成一个圈,每人手里都握着一个令牌写明一个数字(随机生成的)。从第一个人开始玩“击鼓传花”游戏,第一个击的次数为其令牌上写明的数字数(假设为m1)。第m1个人出列。下次再从第m1+1个人开始新的“击鼓传花”击的次数也为其令牌上写明的次数,等于该次数的人出列。重复以上过程直到所有人都出列为止。
这个题用双向循环链表来做更省劲。
注意:
1、输出的是出列人所在的位置编号,不是他手中令牌的数字
2、寻找下一个出列的人时,不要按照令牌上的数字往下跑,假如一共5个人,令牌上的数是5000,就活生生地在这5个元素中循环1000次,是不是太傻了。解决这个问题看第113行代码,令牌上的数字对元素个数取余才是向下寻找的步数。
3、OJ不要用 /b (退格)来删除多余的空格,我因为这个把自己坑了
AC代码:
#include <iostream> #include <stdio.h> #define OK 1; #define ERROR 0; #define OVERFLOW -2; using namespace std; typedef int ElemType;//定义数据项类型 typedef int Status; //用于返回函数执行结果状态 class DuLNode { private: typedef struct SNode{ ElemType data; //元素数据 int id; //序号 SNode *prior; //前驱 SNode *next; //后继 }SDuLNode; int num; //元素个数 SDuLNode *first; //指向第一个元素 SDuLNode *last; //指向最后一个元素 SDuLNode *current; //指向当前“花”的位置 public: DuLNode(): num(0),first(NULL),last(NULL),current(NULL) {} public: Status PushBack(ElemType n) { if (first == NULL) { //插入第一个元素 SDuLNode *sn = new SDuLNode; sn->data = n; sn->id = ++num; sn->next = sn; sn->prior = sn; current = first = last = sn; } else { SDuLNode *sn = new SDuLNode; last->next = sn; //sn的前驱指向sn first->prior = sn; //first的前驱指向sn sn->data = n; sn->id = ++num; sn->next = first; sn->prior = last; last = sn; //last指向最后一个元素 } return OK; } Status DeleteCurrent() { //删除“花” if (num == 0) return ERROR; SDuLNode *temp_del = current; current->prior->next = current->next; current->next->prior = current->prior; if (current == first) first = current->next; if (current == last) last = current->prior; current = current->next; delete temp_del; --num; return OK; } void Clear() { //清空 if (current != NULL) while(DeleteCurrent()); } ElemType CurrentData() { //返回花手中令牌数字 return current->data; } int CurrentID() { //返回花的所在位置 return current->id; } int Size() { //当前人数 return num; } void MoveNext() { //花后移一位 current = current->next; } }; int main() { int t; cin >> t; for (int i=1;i<=t;i++) { int n; DuLNode peo; cin >> n; for (int j=0;j<n;j++) { int num; cin >> num; peo.PushBack(num); } printf("Case #%d:\n",i); int psize = peo.Size(); for (int j=1;j<psize;j++) { int mi = peo.CurrentData() % peo.Size(); for (int l=0;l<mi;l++) peo.MoveNext(); if (j == 1) cout << peo.CurrentID(); else cout << " " << peo.CurrentID(); peo.DeleteCurrent(); } if (psize > 1) cout << endl; else cout << "1" << endl; peo.Clear(); //将申请的内存清干净 } return 0; }