日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

假币问题 (n枚硬币+未知轻重+DFS)

發(fā)布時間:2023/12/18 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 假币问题 (n枚硬币+未知轻重+DFS) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題目描述

n(n>=3)n(n>=3)n(n>=3)枚硬幣中有一枚重量不合格的硬幣(過輕或者過重),若只有一架天平可以用來稱重,且稱重的硬幣數(shù)量沒有限制,設(shè)計一個算法找出這枚不合格的硬幣,使得稱重次數(shù)最少

題目分析

本題用的是減治法,我找了很多網(wǎng)上的寫法,但是沒有符合我想象中的代碼,或者就是題目略有不同,所以決定自己寫一個。寫的時候花了很長時間處理邊界問題。
注意本題是n枚硬幣,并且沒有事先告知硬幣是偏重還是偏輕,因此如果就是根據(jù)重量的大小來判斷,無法得到正確的答案。

遞歸C++

主要的思想是根據(jù)數(shù)組的奇偶來分:

  • 長度為奇數(shù)時,先不考慮第一個元素,對往后的元素分兩段求和,判斷它們的大小。如果不相等,則先后遞歸處理左右兩段。如果相等,并且第一個元素不等于第二個元素(這個條件很重要,若只是后面兩段相等,并不能得出第一個元素就是假幣),那么第一個元素就是假幣
  • 長度為偶數(shù)時,將數(shù)組分成長度相等的兩段,并分別求和。若相等,則假幣不在這個區(qū)間里;若不等,遞歸處理左右兩段
#include <iostream> #include <vector> #include <ctime> #include <algorithm> using namespace std; vector<int> coins; int N;void make_coins() {int tweight = rand() % 10 + 1; //生成[1,10]之間的隨機數(shù)代表真硬幣重量 for (int i = 0; i < N; i++) coins[i] = tweight;int fweight = rand() % 20 + 1; //生成[1,20]之間的隨機數(shù)代表假硬幣重量int pos = rand() % N; // 生成[0,N)之間的隨機數(shù),代表假硬幣的位置while (fweight == tweight) fweight = rand() % 20 + 1;coins[pos] = fweight; // codeslogan }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) {// 當剩余的長度為2時,根據(jù)當前兩個元素的大小,及它們的前后關(guān)系判斷 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;}// 當剩余長度為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; // codeslogan}int pos = -1;if (n % 2 == 0) { // 長度為偶數(shù)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 { // 長度為奇數(shù)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; // 隨機生成[3,33)之間的數(shù),代表n枚硬幣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("經(jīng)遍歷驗證,答案正確!\n");else printf("答案錯誤!\n");return 0; }

總結(jié)

以上是生活随笔為你收集整理的假币问题 (n枚硬币+未知轻重+DFS)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。