1. 程式人生 > >占卜DIY【雙端佇列+模擬】

占卜DIY【雙端佇列+模擬】

題目描述 lyd學會了使用撲克DIY占卜。方法如下:一副去掉大小王的撲克共52張,打亂後均分為13堆,編號1~13,每堆4張,其中第13堆稱作“生命牌”,也就是說你有4條命。這裡邊,4張K被稱作死神。 初始狀態下,所有的牌背面朝上扣下。 流程如下: 1.抽取生命牌中的最上面一張(第一張)。 2.把這張牌翻開,正面朝上,放到牌上的數字所對應編號的堆的最上邊。(例如抽到2,正面朝上放到第2堆牌最上面,又比如抽到J,放到第11堆牌最上邊,注意是正面朝上放) 3.從剛放了牌的那一堆最底下(最後一張)抽取一張牌,重複第2步。(例如你上次抽了2,放到了第二堆頂部,現在抽第二堆最後一張發現是8,又放到第8堆頂部…)

4.在抽牌過程中如果抽到K,則稱死了一條命,就扔掉K再從第1步開始。 5.當發現四條命都死了以後,統計現在每堆牌上邊正面朝上的牌的數目,只要同一數字的牌出現4張正面朝上的牌(比如4個A),則稱“開了一對”,當然4個K是不算的。 6.統計一共開了多少對,開了0對稱作"極凶",12對為“大凶”,3對為“凶”,45對為“小凶”,6對為“中庸”,78對“小吉”,9對為“吉”,1011為“大吉”,12為“滿堂開花,極吉”。

如果還不明白,就去看樣例把。。。

輸入格式 一共13行,為每堆牌的具體牌是什麼(不區分花色只區分數字),每堆輸入的順序為從上到下。 為了便於讀入,用0代表10,那麼A,J,Q,K(大寫)就不用說了吧。。。

輸出格式 一共開了幾對。

提示 註解:第一條命死後前12堆牌變成了這個樣子: A A A 8 K 5 3 2 3 9 6 0 4 4 3 4 5 5 3 4 6 6 5 6 7 7 7 7 8 8 8 9 9 9 0 0 0 K J J J Q A Q//抽到這裡的K死掉了 J Q 2 2 第二條命由於K在生命牌中,所以直接死掉,不變。 第三條命死後前12堆牌變成了這個樣子: A A A A 2 2 2 K 3 3 3 3 4 4 4 4 5 5 5 5 6 6 6 6 7 7 7 7 8 8 8 8 9 9 9 9 0 0 0 0//抽到這裡的K死掉了 J J J Q Q Q J Q 第四條命死後前12堆牌變成了這個樣子: A A A A 2 2 2 2//抽到這裡的K死掉了 3 3 3 3 4 4 4 4 5 5 5 5 6 6 6 6 7 7 7 7 8 8 8 8 9 9 9 9 0 0 0 0 J J J Q Q Q J Q 最後發現在所有已經正面朝上的牌中,A 2 3 4 5 6 7 8 10這9對牌“開”了,(注意,第9堆牌中的最後一張雖然也是9,但是並沒有被翻開!所以不能算)因此輸出9,喔,出題人Lyd的運勢為“吉”哦·T_T。 樣例資料 輸入樣例 #1 輸出樣例 #1 //這是出題人隨手寫下的資料,看看他的運勢如何吧… 8 5 A A K 5 3 2 9 6 0 6 3 4 3 4 3 4 4 5 5 6 7 6 8 7 7 7 9 9 8 8 9 0 0 0 K J J J Q A Q K J Q 2 2 A K Q 2

9

聽說兩天第一題不是小學奧數就是模擬,所以聯賽前刷道模擬(因為是模擬,所以程式碼解釋較為細緻)。。。 分析:資料規模極小的模擬題,隨便怎麼寫,注意細節即可 看完題目很容易想到一種資料結構:雙端佇列(支援刪除兩端的元素),雖然你可以用for過,但是說實話寫雙端佇列會好理解得多 這裡要注意得幾個問題 1.如何判斷一個數字是否正面朝上?因為數字的個數可以有4個,然而同樣的牌只有一張(即第一張牌,第二張牌…),所以我們存牌的資訊 2.注意A是1,J是11,Q是12,K是13

#include<cstdio>
#include<iostream>
#include<cstring>
#include<deque>
using namespace std;
struct Node
{
	int Num,id;//數字,編號 
	bool If;//If==1表示正面朝上 
}xinxi[100];//xinxi[i]表示第i張牌的資訊 
deque<Node> q[20];//q【i】表示第i堆牌 
char a;
int Life=4;//4條命 
int ans,sum[20];
int main()
{
	int Num;
	for(int i=1;i<=13;i++)
	{
		for(int j=1;j<=4;j++)
		{
			cin>>a;
			if(a=='0') Num=10;
			if(a=='J') Num=11;
			if(a=='Q') Num=12;
			if(a=='K') Num=13;
			if(a=='A') Num=1;
			if(a>='2'&&a<='9') Num=a-48;
			xinxi[((i-1)<<2)+j].Num=Num;
			xinxi[((i-1)<<2)+j].If=0;
			xinxi[((i-1)<<2)+j].id=((i-1)<<2)+j;//從上到下從左到右依次編號 
			q[i].push_back(xinxi[((i-1)<<2)+j]);
		}
	}
	int x,l;
	while(Life)//在沒死之前 
	{
		Num=13;//第一步 
		x=q[Num].front().Num,l=q[Num].front().id;
	    xinxi[l].If=1;//第l張牌正面朝上 
		q[Num].pop_front();
		if(x==13)//如果第l張牌的數字是K 
		{
			Life--;
			continue;
		}
		q[x].push_front(xinxi[l]);
		Num=x;
		do
		{
			x=q[Num].back().Num,l=q[Num].back().id;
			xinxi[l].If=1;
			q[Num].pop_back();
			if(x==13) break;
			q[x].push_front(xinxi[l]);
			Num=x;
		}while(1);//以上迴圈請嘗試自己看懂 
		Life--;//抽到了K,Life-- 
	}
	for(int i=1;i<=13;i++)//一共有13堆牌 
	{
		memset(sum,0,sizeof(sum));//第i堆中,sum【j】表示數字為j的牌的個數 
		while(!q[i].empty())//統計每一堆牌正面朝上的數字的個數 
		{
			if(q[i].front().If==1)
			sum[q[i].front().Num]++;
			q[i].pop_front();
		}
		for(int j=1;j<=12;j++)//除K外一種有12種牌 
		if(sum[j]==4) ans++;//如果一堆中有一種牌連續4張,答案加一 
	}
	printf("%d",ans);
	return 0;
}

謝謝