THU資料結構程式設計作業一 祖瑪(Zuma)

2021-07-05 10:13:32 字數 4061 閱讀 4319

描述

祖瑪是一款曾經風靡全球的遊戲,其玩法是:在一條軌道上初始排列著若干個彩色珠子,其中任意三個相鄰的珠子不會完全同色。此後,你可以發射珠子到軌道上並加入原有序列中。一旦有三個或更多同色的珠子變成相鄰,它們就會立即消失。這類消除現象可能會連鎖式發生,其間你將暫時不能發射珠子。

開發商最近準備為玩家寫乙個遊戲過程的回放工具。他們已經在遊戲內完成了過程記錄的功能,而回放功能的實現則委託你來完成。

遊戲過程的記錄中,首先是軌道上初始的珠子序列,然後是玩家接下來所做的一系列操作。你的任務是,在各次操作之後及時計算出新的珠子序列。

輸入

第一行是乙個由大寫字母』a』~』z』組成的字串,表示軌道上初始的珠子序列,不同的字母表示不同的顏色。

第二行是乙個數字n,表示整個回放過程共有n次操作。

接下來的n行依次對應於各次操作。每次操作由乙個數字k和乙個大寫字母σ描述,以空格分隔。其中,σ為新珠子的顏色。若插入前共有m顆珠子,則k ∈ [0, m]表示新珠子嵌入之後(尚未發生消除之前)在軌道上的位序。

輸出

輸出共n行,依次給出各次操作(及可能隨即發生的消除現象)之後軌道上的珠子序列。

如果軌道上已沒有珠子,則以「-」表示。

樣例

input

accba

51 b0a

2 b4 c

0a

output

abccba

aabccba

aabbccba

-a

限制0 ≤ n ≤ 10^4

0 ≤ 初始珠子數量 ≤ 10^4

記憶體:256 mb

提示

列表先上整個程式:

#include

#include

#include

#define maxsize 20000

using

namespace

std;

const

int sz = 1

<<20; //fast io

struct fastio

}io;

int main()

s[sz++] = '\0';

int times;

scanf("%d", ×);

int (*insert)[2] = new

int[times][2]();

for(int i = 0; i < times; ++i)

scanf("%d %c", &insert[i][0], &insert[i][1]);

for(int i = 0, j = 0; i < times; ++i)

//move p2

while(!p2stop)

if(rep >= 3)

//reset rep

if(rep >=3 && s[p1] == s[p2])

}if(p2 - p1 >= 2)

/*******************************/

/* bool flag = true;

if(sz >= 4)

if(tt >= 3) }}

}*/if(sz <= 1)

printf("-\n");

else

printf("%s\n", s);

}delete insert;

return

0;}

以下對程式的部分內容進行解釋:

1、 oj上測試的資料量是非常大的,所以在設計程式時必須考慮時間複雜度。首先為了實現快速輸入輸出,調大流緩衝區。

const

intsz = 1

<<20;

struct fastio

}io;

開始在oj上測試時候總是只能通過95%,對於最後一組資料總是超時,而且在程式演算法改進了以後(稍後會進行說明),依然超時,改進後的演算法的時間複雜度應該是極大地降低了的。因為以前在自己的 linux 虛擬機器上測試過資料量較大的資料總是出錯,我就考慮到是否是和輸入輸出快取有關係,畢竟自己只是剛入門的菜鳥,對快取並沒有足夠的了解。在網上搜了很多,都提到了擴大緩衝區但是基本都沒有解決方法。直到看到這位大神的**,才恍然大悟: 。後來測試不僅最後一組資料通過而且速度也很快。我將這段**加到前乙個「範圍查詢」的程式中,速度果然加快了很多,膜拜大神~~~

int (*insert)[2] = new

int[times][2]();

for(int i = 0; i < times; ++i)

scanf("%d %c", &insert[i][0], &insert[i][1]);

雖然整個陣列為整形,但是我通過 scanf 將陣列的第二列調整輸入為 char 型,這樣就可以儲存想要儲存的資料,並能夠方便獲取。

3、程式的主題部分是個大的 for 迴圈。對於每乙個有待插入的字元,首先進行插入 :

for( j = sz - 1; j >= insert[i][0]; --j)

s[j+1] = s[j];

s[j+1] = insert[i][1];

++sz;

後面就是對於連續出現的字串行進行刪除了。

起初,我使用的唄注釋掉的那部分方法。通過對插入後的序列進行逐論掃瞄,每次掃瞄都刪除乙個連續字串行,這種方法很笨但是確實很好實現。

bool flag = true;

if(sz >= 4)

if(tt >= 3) }}

}

在oj上測試後最後一組資料超時無法通過,我以為是因為自己的程式方法太笨複雜度較高引起的超時,其實主要的原因應該是前面提到的流快取不夠大的原因。但是以上錯誤的認為,讓我不得不重新考慮演算法的實現。

4、重新思考演算法的實現。上面的方法在字元刪除上耗時應該是最多了,每次都要對字串行進行掃瞄,而且每次掃瞄只能刪除一組重複序列,效率是很低的。於是,我希望找到一種方法提前知道哪些元素會被刪除,最後一次性刪除所有資料,這樣就只需要一次刪除操作。

想到了用指標的方法(我這裡用的是陣列的下標)進行標記。首先設定兩個標誌都指向插入點的字元,然後將兩個標誌分別向左和向右移動,記錄字元,當左右指標對於同乙個字元記錄的次數大於等於3 的時候就說明兩個指標之間的字串是需要刪除的。

整個過程如下圖:

紅色的 c 是插入的字元,rep用來記錄重複次數。

···首先指標p1和p2都指向插入位置,然後分別向左和向右移動直到遇到不同的字元就停止;

···如果當兩個指標都停止時候的rep的值大於等於3,則確定p1和p2之間的字元是需要刪除的。

···此時,如果p1 和 p2 所指向的字元相同,則說明有可能後續的字元還需要刪除,於是將rep置為2,並再次移動p1和p2,同時記錄rep,如此反覆。

···直到p1 和p2指向不同的字元或者已經移動到字串兩端。

整個過程也並不複雜,首先的難點是如果p1 和 p2 向兩邊移動停止時rep小於3時,如何確定之前記錄的需要刪除的字串的位置,我這裡增加了兩個變數p1 和p2來記錄前一次確定需要刪除的字串的位置。其次,當其中乙個指標移動到字串的一端時,端點的字串可能需要刪除也可能不需要刪除,這是比較難確定的。這裡我增加了乙個判斷來解決這個問題:

if(rep >= 3)
被這兩個問題折磨的不要不要的~~~~ ヾ(≧o≦)〃嗷~

最後測試,發現執行明顯快了不少。

另:寫到這裡,發現其實開始的插入操作也可以沒有的,直接記錄要插入的位置和字元,然後只需要做刪除操作不就好了!發現自己智商又捉急了~ヾ(≧o≦)〃嗷~ヾ(≧o≦)〃嗷~ヾ(≧o≦)〃嗷~

資料結構(Tsinghua 祖瑪 Zuma )

祖瑪是一款曾經風靡全球的遊戲,其玩法是 在一條軌道上初始排列著若干個彩色珠子,其中任意三個相鄰的珠子不會完全同色。此後,你可以發射珠子到軌道上並加入原有序列中。一旦有三個或更多同色的珠子變成相鄰,它們就會立即消失。這類消除現象可能會連鎖式發生,其間你將暫時不能發射珠子。開發商最近準備為玩家寫乙個遊戲...

資料結構作業

一,思維導圖 二,概念筆記 1,在計算時間複雜度的時候一般有 o 1 2 n 2,在計算平均時間複雜度時對p i t i 求和,其中p i 是概率,t i 是每個i的時間複雜度。3,儲存密度等於節點中個元素所佔的儲存量除以結點所佔的儲存量,儲存密度越大儲存空間的利用率越高。4,每次出棧只能出棧棧頂元...

資料結構程式設計

1 陣列部分 雜湊表思想 雜湊表也稱為雜湊表,是演算法終於時間和空間作出權衡的經典例子。當乙個表所有的鍵都是小整數時,便可以使用乙個陣列來實現無序的符號表,將鍵作為陣列的索引而陣列i中所儲存的值就是該鍵所對應的鍵值,即key value對應。雜湊表的思想也是這樣子的,只是雜湊表的鍵的型別更為複雜而已...