魔術師發牌問題---來自演算法之美
阿新 • • 發佈:2019-01-12
魔術師手中有A、2、3……J、Q、K十三張黑桃撲克牌。在表演魔術前,魔術師已經將他們按照一定的順序疊放好(有花色的一面朝下)。魔術表演過程為:一開始,魔術師數1,然後把最上面的那張牌翻過來,是黑桃A;然後將其放到桌面上;第二次,魔術師數1、2;將第一張牌放到這些牌的最下面,將第二張牌翻轉過來,正好是黑桃2;第三次,魔術師數1、2、3;將第1、2張牌依次放到這些牌的最下面,將第三張牌翻過來正好是黑桃3;……直到將所有的牌都翻出來為止。問原來牌的順序是如何的。
陣列實現:
#include<iostream> using namespace std; int main(){ int a[13]; for(int i=1;i<13;i++){ a[i]=0; } a[0]=1; int n=1; for(int i=2;i<14;i++){ for(int j=0;j<i;){ if(a[n%13]==0){ j++; if(j==i){ a[n%13]=i; break; } } n++; } } for(int i=0;i<13;i++){ cout<<a[i]<<" "; } return 0; }
連結串列實現:
#include <iostream> using namespace std; #define N 13 typedef struct Node { int data; Node *next; }Node,*LinkList; void InitLinkList(LinkList &L, int n) { L = new Node; L->next = L; LinkList p; for(int j = 0; j < n; ++j) { p = new Node; p->data = 0; //初始值為零 p->next = L->next; //新節點指向原來的第一個節點 L->next = p; //頭節點指向新的節點 } } void Magician(LinkList &L, int n) { LinkList p = L->next; p->data = 1; //第一張牌是1 for(int num = 2; num <= n; ++num) //依次找到2-n牌的位置 { int i = 0; while(i < num) { p = p->next; if(p->data == 0) ++i; //該位置有牌應該跳過 } p->data = num; } } void Print(LinkList &L) { LinkList p = L->next; cout << "Print: "; while(p != L) { cout << p->data << " "; p = p->next; } cout << endl; } int main() { LinkList L; InitLinkList(L, N); Magician(L, N); Print(L); }
如果是數一張翻一張呢?
//逆著模擬,最後一張牌是13,接著12.....,f是頭部標記,r是尾部標記 #include<iostream> using namespace std; int main(){ int a[100]; int f,r; f=0,r=1; a[0]=13; for(int i=12;i>=1;i--){ a[r++]=i; a[r++]=a[f++]; } for(int i=r-1;i>=f;i--) cout<<a[i]<<' '; cout<<endl; return 0; }
#include<iostream>
using namespace std;
int main(){
int a[13];
int n=0;
for(int i=0;i<13;i++){
a[i]=0;
}
for(int i=1;i<=13;i++){
for(int j=0;;n++){
if(a[n%13]==0){
j++;
if(j==2){
a[n%13]=i;
break;
}
}
}
}
for(int i=0;i<13;i++){
cout<<a[i]<<" ";
}
return 0;
}