生活随笔
收集整理的這篇文章主要介紹了
假币问题 (n枚硬币+未知轻重+DFS)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目描述
在n(n>=3)n(n>=3)n(n>=3)枚硬幣中有一枚重量不合格的硬幣(過輕或者過重),若只有一架天平可以用來稱重,且稱重的硬幣數量沒有限制,設計一個算法找出這枚不合格的硬幣,使得稱重次數最少。
題目分析
本題用的是減治法,我找了很多網上的寫法,但是沒有符合我想象中的代碼,或者就是題目略有不同,所以決定自己寫一個。寫的時候花了很長時間處理邊界問題。
注意本題是n枚硬幣,并且沒有事先告知硬幣是偏重還是偏輕,因此如果就是根據重量的大小來判斷,無法得到正確的答案。
遞歸C++
主要的思想是根據數組的奇偶來分:
- 長度為奇數時,先不考慮第一個元素,對往后的元素分兩段求和,判斷它們的大小。如果不相等,則先后遞歸處理左右兩段。如果相等,并且第一個元素不等于第二個元素(這個條件很重要,若只是后面兩段相等,并不能得出第一個元素就是假幣),那么第一個元素就是假幣
- 長度為偶數時,將數組分成長度相等的兩段,并分別求和。若相等,則假幣不在這個區間里;若不等,遞歸處理左右兩段
#include <iostream>
#include <vector>
#include <ctime>
#include <algorithm>
using namespace std
;
vector
<int> coins
;
int N
;void make_coins() {int tweight
= rand() % 10 + 1; for (int i
= 0; i
< N
; i
++) coins
[i
] = tweight
;int fweight
= rand() % 20 + 1; int pos
= rand() % N
; while (fweight
== tweight
) fweight
= rand() % 20 + 1;coins
[pos
] = fweight
;
}int sum_arr(int l
, int r
) {int sum
= 0;for (int i
= l
; i
<= r
; i
++) sum
+= coins
[i
];return sum
;
}int dfs(int n
, int l
, int r
) {if(n
== 2) { if (coins
[l
] != coins
[r
]) {if ((l
-1) >= 0) return coins
[l
-1] == coins
[l
]? (r
+1):(l
+1);else return coins
[r
+1] == coins
[l
]? (r
+1):(l
+1);}return -1;}if (n
== 1) {if ((l
-1) >= 0 && coins
[l
-1] != coins
[l
] && coins
[l
] != coins
[l
+1]) return l
+1;if ((l
-1) < 0 && coins
[r
+1] != coins
[r
] && coins
[r
+2] != coins
[r
]) return r
+1;return -1; }int pos
= -1;if (n
% 2 == 0) { int rr
= l
+(r
-l
)/2; int left
= sum_arr(l
, rr
);int right
= sum_arr(rr
+1, r
);if (left
!= right
) {pos
= dfs(n
/2, l
, rr
);if (pos
!= -1) return pos
;pos
= dfs(n
/2, rr
+1, r
);if (pos
!= -1) return pos
;}} else { int rr
= l
+(r
-l
)/2;int left
= sum_arr(l
+1, rr
);int right
= sum_arr(rr
+1, r
);if (left
== right
) {if (coins
[l
] != coins
[l
+1]) pos
= l
+ 1;}else {pos
= dfs(n
/2, l
+1, rr
);if (pos
!= -1) return pos
;pos
= dfs(n
/2, rr
+1, r
);if (pos
!= -1) return pos
;} }return pos
;
}void PrintOut() {for (auto t
: coins
) cout
<< t
<< ' ';cout
<< endl
;
}
bool check_ans(int n
) {int val
= coins
[n
];int idx
;for (int i
= 0; i
< coins
.size(); i
++) if (val
== coins
[i
]) {idx
= i
; break;}if (idx
== n
) return true;else return false;
}int main() {srand((unsigned int)time(NULL));N
= rand() % 30 + 3; coins
.resize(N
); make_coins();PrintOut();int pos
= dfs(N
, 0, N
-1);printf("共有%d枚硬幣\n", N
);printf("假幣重量為%d,位于第%d個位置\n", coins
[pos
-1], pos
);bool flag
= check_ans(pos
-1);if (flag
) printf("經遍歷驗證,答案正確!\n");else printf("答案錯誤!\n");return 0;
}
總結
以上是生活随笔為你收集整理的假币问题 (n枚硬币+未知轻重+DFS)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。