208 37 賴昭勳
機器人專題課 程式作業
現在欲在最少的基本操作數內,使其中一個杯子內的水容量是\(x\),輸出倒水的方法。
將每一種狀態(各水杯的容量) 視為一個節點,節點 \((u, v)\)間若可以在一個操作內達成,則連一條有向邊\(u \rightarrow v\)。
問題則可以變成,所有含有容量\(x\)的狀態為「終點」,一開始所有杯子都是空的狀態為起點,找出一條起點到任一終點的最短路徑。
簡單來說流程(pseudocode)就是:
目前的距離 \(dis = 0\)
找過的點 \(vis = [起點]\)
while (沒找到終點)
for \(v\) in vis:
將\(v\)所有連到且沒找過的點\(u\)加入 vis
如果找到終點就停止執行
dis += 1
顯然,\(x\)次執行後所有離起點\(x\)的點都會被看到。
可以用數學歸納法證明。
因此最短路徑如果是\(y\),他就必然在\(y\)步時被找到。
對每個節點紀錄 \(p[i]\),代表轉移到該節點的節點(類似樹狀圖的父親概念)。
最後從終點一路沿著\(p[i]\)往起點回朔就能得到解答的路徑(反轉)。
1
1
2
3
3
8
16
8
for(i=1;i<=qe;i++)
{
flag = 0;
// for(j=1;j<=n;j++) if(c[j]!=que[i][j]) flag = 1;
for(j=1;j<=n;j++)
if(c[j]!=que[i][j])
{ // 有不同的量杯水量,不是相同的組合(break後可繼續比對下一個queue值)
flag = 1;
break;
}
if(flag==0) return 0; // 完全相同的量杯水量組合(不必再放到queue中了)
}
return 1; // queue中無此c[1..5]組合紀錄(必須push到queue中)
每次檢查所有以前的狀態,查詢複雜度\(O(狀態數) = O(n)\)
From: 彭天健老師
高中資訊課程
插入/查詢時間複雜度: \(O(1)/O(1)\)
空間複雜度:???
如果每個杯子的容量分別是\(c_1, c_2, ..., c_n\),
則基本上有\(\Pi_{i=1}^n c_i\)那麼多種狀態,更何況我們無法事先知道每個杯子的水量,這樣會浪費很多記憶體空間。
ex. Jiwfoehid -> Jiw
EWIIED -> EWI
JiwHEFID -> Jiw
因為輸入的種類數很多,輸出種類數卻很少,一定會存在兩個以上不同的輸入得到一樣的雜湊值。
解決方法:
插入數值時:放在雜湊值後面第一個是空的位置。
查詢數值是否存在時:持續查詢直到遇到雜湊值後面第一個空位。
空間可以自訂(不能低於可能出現的狀態數)
時間: 如果雜湊函數是好的話,期望在查詢和插入都是\(O(1)\)
我使用了"Rolling Hash" 也就是將各杯子的水量視為一個多項式的係數f(x),並求f(k) mod m 的結果。