對英雄會中彩色石子問題的思考

2021-06-21 21:48:46 字數 2980 閱讀 8982

這是csdn英雄會中的一道題,詳見:原題鏈結.題目如下:有一行彩色的棋子,每個棋子的顏色是k種顏色之一.你不能改變棋子的順序,但是可以移走一些棋子。問至少移走多少個石子,才能使得

兩個同色得石子之間沒有其他顏色的棋子?(

額...原題怎麼一會石子一會又棋子的)

輸入格式:

多組資料,每組資料兩行,第一行是兩個整數n和k, 1<=n<=100, 1<=k<=5

下一行是n個在[1..k]範圍內的正整數,代表每個棋子的顏色。

輸出格式:

每組測試資料輸出一行包含乙個整數,表示至少移走的石子數。

10 3

2 1 2 2 1 1 3 1 3 3

輸出樣例: 2

注:可以移走第2個第7個棋子。

就是對所有的取法都判斷是否滿足"兩個同色的棋子之間沒有其他顏色的棋子"這一條件,最後再從滿足此條件的所有結果中找出取走棋子個數最少的作為結果返回.思路沒有錯,但是執行結果也很明顯:嚴重超時.

通過思考可以得到一條重要的先驗知識:

連成一串的相同顏色的棋子的取法是相同的

也就是說:在最優的取法中要麼把連成一串的相同顏色的棋子全部取走,要麼全部留下.例如輸入樣例中第3,4位置的"2",

可以用反證法證明:若最優取法中把某一串相同顏色的棋子取走了一部分留下了一部分,那麼把從這一串中取走的棋子留下能有更優的結果.有了這條先驗知識我們就可以把"一串相同顏色的棋子"當做乙個整體來處理,我們之後稱之為"串",這樣能夠提高我們處理的速度.儘管這樣,我們的結果仍然是:超時.

注意到:只要搜尋到取走棋子最少的取法即可,沒有必要把所有結果搜尋一遍.也就是我們可以先判斷所有的取走1個棋子的取法是否滿足條件,若有滿足條件的則結果為1,否則判斷所有的取走2個棋子的取法是否滿足條件,若有滿足條件的則結果為2,......考慮到"串"的大小不一,實際的執行過程還要做改進,改進後的**如下:

#include #include #include using namespace std;

typedef unsigned int uint;

struct numandcnt//就是顏色+連續出現的個數

;struct path

;bool operator

else

}uint compute(vector&);

bool isok(vector& vtr_in);

//把幾個int裝換成numandcnt格式

void ints2numandcnts(vector& in,vector& ret);

void main()

cout

vectorvtr_numcnt;

ints2numandcnts(vtr_ints,vtr_numcnt);

priority_queuepaths;//所有當前要處理的方案

path path_init;

path_init.dist =0;

for(uint i=0;i=1)

;class infoofaclr//一種顏色的資訊,

;//下面這個要進行遞迴

uint compute(const vector& in);

//把幾個int裝換成clrandcnt格式

void ints2numandcnts( const vector& in,vector& ret);

//掃瞄乙個vectorvoid getinfo(const vector& in,vector& ret);

void main()

ints2numandcnts(vtr_ints,vtr_clrandcnt);

cout

}//之後也相當於vtr_cacforme初始化了

uint delmin=1000;

for(int idxlastforme=0;idxlastformevtr_cacforthis=vtr_cacforme;

uint thisdelstonescnt=0;

uint thisdelcnt=0;

for(uint idx=0;idx<=info.vtr_idxall[idxlastforme]-basicdelcnt;idx++)

}if(idxlastforme!=info.vtr_idxall .size ()-1)

}} while(info.vtr_idxall[idxlastforme]-basicdelcnt-thisdelcnt!=0)

vector::iterator itr;

itr=vtr_cacforthis.begin ();

while(itr!=vtr_cacforthis.end ())

else

}uint delforthis=thisdelstonescnt+compute(vtr_cacforthis);

if(delmin>delforthis)

} return delmin+basicdelstonescnt;

}uint compute(const vector& vtr_clrandcnt)

vectorvtr_infoscan;

getinfo(vtr_clrandcnt,vtr_infoscan);

uint firstclr=vtr_clrandcnt[0].clr ;

uint fstclrlast=vtr_infoscan[firstclr].idx_last;

vectorclrshead;

//尋找所有可以作為頭的顏色

for(uint i=1;inowdel)

} return min;

}void ints2numandcnts(const vector& in,vector& ret)

//開始掃瞄

for(uint i=0;i

中間有許多**寫的不夠簡潔,講解不夠清楚,並且應該還有高效的演算法,還望大神指正.

對幾個問題的思考

1.碟符為什麼從c開始。2.fat32 和ntfs 區別 為什麼fat32 最大單檔案只支援4g 3.本機是xp能否相容win7系統虛擬機器,能否共享檔案。第乙個問題很簡單,公尺老師講過但有多少人能現在回答上這個問題呢。你你你。能回答嗎?當這個問題擺在我的面前的餓時候我沒有回答上來。只有乙個影響就是...

對電瓶車管控問題的思考

聽老師在課堂上吧啦吧啦了一堆,講的都是現如今電瓶車氾濫 不講交通規則等等對交通的妨礙。作為乙個在家時天天騎電動車到處飛奔,速度到六十邁的人,我坐在下面瑟瑟發抖。我媽不懂複雜的交通規則,而我在拿到駕照前也不懂。我們知道的不過是行人靠右,紅燈停綠行等,不知道紅燈時可以右拐彎,不知道轉彎要打轉向燈,也不知...

對區塊鏈技術幾個問題的思考

為什麼pow達成共識的週期較長?在像位元幣這種公有鏈中,節點的數量是巨大的,而其基礎p2p網路中每個節點都連線相對有限的節點,當有節點需要傳送交易到全網時,其進行一次全廣播是非常耗時的,當然產生新塊後,全網廣播也是非常耗時的。如果達成共識的時間設定的太短,對造成位元幣頻繁的分叉,造成系統不穩定,影響...