日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/18 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 假币问题 (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; //生成[1,10]之間的隨機數代表真硬幣重量 for (int i = 0; i < N; i++) coins[i] = tweight;int fweight = rand() % 20 + 1; //生成[1,20]之間的隨機數代表假硬幣重量int pos = rand() % N; // 生成[0,N)之間的隨機數,代表假硬幣的位置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時,根據當前兩個元素的大小,及它們的前后關系判斷 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) { // 長度為偶數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; // 隨機生成[3,33)之間的數,代表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("經遍歷驗證,答案正確!\n");else printf("答案錯誤!\n");return 0; }

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。