1. 程式人生 > >魔術師發牌問題---來自演算法之美

魔術師發牌問題---來自演算法之美

      魔術師手中有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;
}