藍橋杯 約數倍數選卡片

2021-07-27 05:55:20 字數 1937 閱讀 3973

問題描述

閒暇時,和華生玩乙個遊戲:

在n張卡片上寫有n個整數。兩人輪流拿走一張卡片。要求下乙個人拿的數字一定是前乙個人拿的數字的約數或倍數。例如,某次福爾摩斯拿走的卡片上寫著數字「6」,則接下來華生可以拿的數字包括:

1,2,3, 6,12,18,24 ....

當輪到某一方拿卡片時,沒有滿足要求的卡片可選,則該方為輸方。

請你利用計算機的優勢計算一下,在已知福爾摩斯所有卡片上的數字和可選哪些數字的條件下,怎樣選擇才能保證必勝!

當選多個數字都可以必勝時,輸出其中最小的數字。如果無論如何都會輸,則輸出-1。

輸入格式

輸入資料為2行。第一行是若干空格分開的整數(每個整數介於1~100間),表示當前剩餘的所有卡片。

第二行也是若干空格分開的整數,表示可以選的數字。當然,第二行的數字必須完全包含在第一行的數字中。

輸出格式

程式則輸出必勝的招法!!

樣例輸入

2 3 6

3 6樣例輸出

3樣例輸入

1 2 2 3 3 4 5

3 4 5

樣例輸出

4 —————————————————————————————————————————

這題我原以為只是個dfs沒什麼坑,結果做了兩個晚上才ac了。一共5組測試資料,最後兩組一直超時。而且不是超時個幾秒,自己電腦放著讓程式跑了幾分鐘都沒有出結果。

首先先明白這是一道用深度搜尋做的題目,也就是要對可能的情況進行搜尋判斷,這本是一種暴力的方式,要減少時間複雜度就要想辦法「剪枝」,即減少對不必要判斷的可能性的搜尋,或者盡量早的搜尋到答案並結束搜尋。

看了別人ac的**後才明白,我的錯誤無論從**上看還是從邏輯上看都只是一點點,即每次選卡片時都要盡量選數字大的,從大到小的選擇卡片。就這麼一句話,在**上的體現僅僅是乙個for迴圈中i要從大到小遞減,但是效率卻是驚人的天壤之別。大家可以自己上機體會一下。

那麼為什麼要盡量選數字大的卡片呢?因為一般來說,大的數的約數倍數少。很簡單,比如說同時存在有2 4 6 三張卡片本輪可選,如果選擇了2 ,那麼在後續的回合中還要對4和6進行搜尋。如果選擇了最大的6,那麼下次只要對2進行搜尋而不用對4進行搜尋,省去了一次。規模大時,此優化效果相當明顯。

用數字a[i]表示有幾個數字i可以選擇,當a[i]等於時表示已經不能選擇數字i了。用陣列b[i]儲存lenb個輸入第二行的 可選的數字 。vec[i]儲存數字i在當前卡片中的所有倍數和約數。

對可選的數字從小到大依次進行一次深度搜尋,如果返回true表示此數字可以選擇,輸出該數字並結束程式。深度搜尋函式帶有引數num和t。

num表示當前最新已選擇的數,t表示當前已選擇數num的是自己還是對手,1表示是自己,此時輪到了對手選擇了。0表示是對手,此時輪到了自己選擇了。如果當前是自己,1,自己贏的條件是num的所有約數倍數都不可選,返回true。如果當前是對手,0,則自己只要有乙個選擇是可以贏的那麼自己就是贏了。

**如下:

#include#include#include#include #include #include using namespace std;

int a[110],b[110];

int lena,lenb,maxx;

vectorvec[110];

bool dfs(int num,int t)

else if(t==0 && dfs(vec[num][i],1-t))// 當前是對手,自己只要有乙個選擇是可以贏的就是贏

}}

a[num]++;

if(t==1)

else

}int main()}}

for(i=0;i='0')

}}

sort(b,b+lenb);//從小到大排列

//將每個數的約數和倍數先存入vector

for(i=1;i<=100;i++)} }

} for(i=0;i

約數倍數選卡片

問題描述 閒暇時,福爾摩斯和華生玩乙個遊戲 在n張卡片上寫有n個整數。兩人輪流拿走一張卡片。要求下乙個人拿的數字一定是前乙個人拿的數字的約數或倍數。例如,某次福爾摩斯拿走的卡片上寫著數字 6 則接下來華生可以拿的數字包括 1,2,3,6,12,18,24 當輪到某一方拿卡片時,沒有滿足要求的卡片可選...

13 4 約數倍數選卡片

閒暇時,福爾摩斯和華生玩乙個遊戲 在n張卡片上寫有n個整數。兩人輪流拿走一張卡片。要求下乙個人拿的數字一定是前乙個人拿的數字的約數或倍數。例如,某次福爾摩斯拿走的卡片上寫著數字 6 則接下來華生可以拿的數字包括 1,2,3,6,12,18,24 當輪到某一方拿卡片時,沒有滿足要求的卡片可選,則該方為...

藍橋杯 PREV 17 約數倍數選卡片(對抗搜尋)

思路 1.這是博弈問題的一般方法,用dfs進行對抗搜尋,遍歷所有可能,雙方在每一步都選取最優步驟 2.單純dfs會超時,我們知道越大的數,它的約數 倍數個數就相對可能越少,因此我們優先遍歷大數即可 include using namespace std bool flag vector int v ...