CSP-Test-DFS大模擬(Gym - 101510B )

DFS的複雜題意大模擬(CSP-T3方向)

題目概述

題目敘述

從瑞神家打牌回來後,東東痛定思痛,決定苦練牌技,終成賭神!
東東有 A × B 張撲克牌。每張撲克牌有一個大小(整數,記爲a,範圍區間是 0 到 A - 1)和一個花色(整數,記爲b,範圍區間是 0 到 B - 1。
撲克牌是互異的,也就是獨一無二的,也就是說沒有兩張牌大小和花色都相同。
“一手牌”的意思是你手裏有5張不同的牌,這 5 張牌沒有誰在前誰在後的順序之分,它們可以形成一個牌型。 我們定義了 9 種牌型,如下是 9 種牌型的規則,我們用“低序號優先”來匹配牌型,即這“一手牌”從上到下滿足的第一個牌型規則就是它的“牌型編號”(一個整數,屬於1到9):
1同花順: 同時滿足規則 5 和規則 4.
2炸彈 : 5張牌其中有4張牌的大小相等.
3三帶二 : 5張牌其中有3張牌的大小相等,且另外2張牌的大小也相等.
4同花 : 5張牌都是相同花色的.
5順子 : 5張牌的大小形如 x, x + 1, x + 2, x + 3, x + 4
6三條: 5張牌其中有3張牌的大小相等.
7兩對: 5張牌其中有2張牌的大小相等,且另外3張牌中2張牌的大小相等.
8一對: 5張牌其中有2張牌的大小相等.
9要不起: 這手牌不滿足上述的牌型中任意一個.
現在, 東東從A × B 張撲克牌中拿走了 2 張牌!分別是 (a1, b1) 和 (a2, b2). (其中a表示大小,b表示花色)
現在要從剩下的撲克牌中再隨機拿出 3 張!組成一手牌!!
其實東東除了會打代碼,他業餘還是一個魔法師,現在他要預言他的未來的可能性,即他將拿到的“一手牌”的可能性,我們用一個“牌型編號(一個整數,屬於1到9)”來表示這手牌的牌型,那麼他的未來有 9 種可能,但每種可能的方案數不一樣。
現在,東東的阿戈摩托之眼沒了,你需要幫他算一算 9 種牌型中,每種牌型的方案數。

INPUT

第 1 行包含了整數 A 和 B (5 ≤ A ≤ 25, 1 ≤ B ≤ 4).
第 2 行包含了整數 a1, b1, a2, b2 (0 ≤ a1, a2 ≤ A - 1, 0 ≤ b1, b2 ≤ B - 1, (a1, b1) ≠ (a2, b2)).

OUTPUT

輸出一行,這行有 9 個整數,每個整數代表了 9 種牌型的方案數(按牌型編號從小到大的順序)

輸入輸出樣例

第一組:
輸入樣例:

5 2
1 0 3 1

輸出樣例:

0 0 0 0 8 0 12 36 0

第二組:
輸入樣例:

25 4
0 0 24 3

輸出樣例:

0 2 18 0 0 644 1656 36432 113344

題目重述

題目一眼就能看出時一道典型的大模擬題:複雜的設定、繁多的場景要求、大量的分支種類,靜下心來分析題目的考察方向和核心算法。
通過劃去無用的場景,可以將問題縮減爲:
給定牌的數值大小和花色數量,範圍內的牌面都可以選用。現給定2張牌面,選擇剩下的三張牌並且形成一套牌面(每張牌不可重複選擇)
對得到的牌面,分成9個類別。要求計算所有得到的牌面,並統計9種牌面出現的次數

解題思路

通過對題意的剖析,可以看出整個任務分成兩個部分:
1、得到所有牌面可能取值
2、根據牌面進行分類並統計個數

任務1解決方案:

注意到題目中是要求遍歷全部的牌面,說到遍歷那就可以清晰地將算法確定到DFS或者BFS上面。,由於在遍歷過程中要求遍歷所有情況且需要判斷牌面所屬類型,方便數據的存儲,選用DFS可以使編碼更爲簡單有效。
(如果選用BFS,要存儲前置節點等問題,增大工作量和錯誤概率)

任務二解決方案:

分析9種牌面我們可以得到下面的分析:
對花色的分類只有兩類:同花 & 非同花
對數值的分類有兩個維度:
1、五張牌是否是順子
2、如果不是順子,有多少張重複的牌型
分析清楚只需要簡單的操作就可以完成分類:
一重判斷–是否同花:遍歷訪問五張牌的花色即可完成
二重判斷–是否順子:使用STL中的sort()函數排序,再判斷五個數值的大小是否階梯性+1增長即可
三重判斷–如果不是順子,初始化一個計數數組統計每個數值的出現次數,分情況寫分支即可解決。

總結

大模擬題,看似題目難懂,十分複雜困難,容易給人帶來畏懼心理。但若能夠沉下心,仔細分析題意,將核心算法與其他任務剝離開,分成模塊解決,一切迎刃而解。

題目源碼

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
int num=0;//要處理的數字個數
int col=0;//要處理的花色個數
struct card
{
    int number;
    int color;
    bool operator<(card & a)
    {
    	return number<a.number;
	}
}cards[5];
int vis [26][5];
int cont=0;
int list[9];
int number_list[26];
void critize(card cin_card[5])
{
	cont++;
	int col_flag=1;
	int num_flag=0;
	int flag_3=0;
	int flag_2=0;
	int col_1=cin_card[0].color;
	card card_copy[5];
	for(int i=0;i<5;i++)
	{
		card_copy[i].number=cin_card[i].number;
		card_copy[i].color=cin_card[i].color;
	}
	sort(card_copy,card_copy+5);
	/*for(int i=0;i<5;i++)
	{
		cout<<card_copy[i].number<<" "<<card_copy[i].color<<endl;
	}*/
	if(card_copy[0].number==card_copy[1].number-1 && card_copy[1].number==card_copy[2].number-1 && card_copy[2].number==card_copy[3].number-1 && card_copy[3].number==card_copy[4].number-1)
	num_flag=5;
	for(int i=0;i<num;i++)
	{
		number_list[i]=0;
	 } 
	for(int i=0;i<5;i++)
	{
		if(card_copy[i].color!=col_1)
		{
			col_flag=0;
		}
		number_list[card_copy[i].number]++;
	}
	for(int i=0;i<num;i++)
	{
		if(number_list[i]==2)
		{
			flag_2++;
		}
		else if(number_list[i]==3)
		{
			flag_3++;
		}
		else if(number_list[i]==4)
		{
			num_flag=4;
			break;
		}
	}
	if(num_flag==5 && col_flag==1)
	{
	list[0]++;
	return;
	}
	if(num_flag==4)
	{
	list[1]++;
	return;
	}
	if(flag_2==1 && flag_3==1)
	{
		list[2]++;
		return;
	}
	if(col_flag==1)
	{
		list[3]++;	
		return;
	}
	if(num_flag==5)
	{
		list[4]++;
		return;
	}
	if(flag_3==1)
	{
		list[5]++;	
		return;
	}
	if(flag_2==2)
	{
		list[6]++;
		return;
	}
	if(flag_2==1)
	{
		list[7]++;
		return;
	}
	list[8]++;
}
void DFS(int step)
{
	for(int i=0;i<num;i++)
		for(int j=0;j<col;j++)
		{
			int dx=i;
			int dy=j;
			if(vis[dx][dy]==0)
			{
				step++;
				cards[step].number=dx;
				cards[step].color=dy;
				vis[dx][dy]=1;
				if(step==4)
				{
					critize(cards);
				}
				else
				{	 
				DFS(step);
				} 
				step--;
				vis[dx][dy]=0; 
			}			
		}	
}
int main()
{
    cin>>num>>col;
    int a1,b1,a2,b2=0;
    cin>>a1>>b1;
    cin>>a2>>b2;
    cards[0].number=a1;
    cards[0].color=b1;
    cards[1].number=a2;
    cards[1].color=b2;
    for(int i=0;i<num;i++)
    	for(int j=0;j<col;j++)
    		vis[i][j]=0;
    vis[a1][b1]=1;
    vis[a2][b2]=1;
    /*for(int i=0;i<num;i++)
    {
    	for(int j=0;j<col;j++)
    	{
    		cout<<vis[i][j]<" ";
		}
		cout<<endl;	
	}*/
	for(int i=0;i<9;i++)
	list[i]=0;
	DFS(1);
	for(int i=0;i<9;i++)
	{
		cout<<list[i]/6<<endl;
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章