【進位制轉換】天平稱重
阿新 • • 發佈:2019-01-21
用天平稱重時,我們希望用盡可能少的砝碼組合稱出儘可能多的重量。
如果只有5個砝碼,重量分別是1,3,9,27,81
則它們可以組合稱出1到121之間任意整數重量
(砝碼允許放在左右兩個盤中)。
本題目要求程式設計實現:對使用者給定的重量,給出砝碼組合方案。
例如:
使用者輸入:
5
程式輸出:
9-3-1
使用者輸入:
19
程式輸出:
27-9+1
要求程式輸出的組合總是大數在前小數在後。
後面(而用到_itoa函式);考慮到最後一位權數一定是+(如果是-,也就是說當前除數是2,那應該是倒數第二位且所得
餘數為2轉成-1,所以最後一個除數一定是1(除數為0時已退出迴圈),那麼餘數也一定是1,所以+),所以對於字串
如果只有5個砝碼,重量分別是1,3,9,27,81
則它們可以組合稱出1到121之間任意整數重量
(砝碼允許放在左右兩個盤中)。
本題目要求程式設計實現:對使用者給定的重量,給出砝碼組合方案。
例如:
使用者輸入:
5
程式輸出:
9-3-1
使用者輸入:
19
程式輸出:
27-9+1
要求程式輸出的組合總是大數在前小數在後。
可以假設使用者的輸入的數字符合範圍1~121。
思路:
聯想二進位制列舉,這裡顯然其實是一種三進位制列舉。
但是有兩個問題:這裡不是選或不選的問題,而是要砝碼放左or放右即+or-表示式的問題,所以顯然用長除法(或者_itoa)直接求得三進製表達式是不行的————如果得到的三進位制值不是由0 1 2組成 而是由0 1 -1組成就好了!
所以這裡需要對長除法(取餘數)變個相,則如果當前餘數是2,就讓它變為-1,那麼顯然當前得到的商需要+1.
這是首要的一個思路。當然對於細節,如長除法中權數應是由小到大(聯想長除法過程)且需要轉成字串加到後面(而用到_itoa函式);考慮到最後一位權數一定是+(如果是-,也就是說當前除數是2,那應該是倒數第二位且所得
餘數為2轉成-1,所以最後一個除數一定是1(除數為0時已退出迴圈),那麼餘數也一定是1,所以+),所以對於字串
的連線處理,最後,丟棄字串的第一位符號。
C語言程式碼:
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include <stdlib.h> #include <string.h> // 天平稱重,進位制解法 char * f2(int n){ char*p = (char*)malloc(1024); memset(p, 0, 1024); int q = 1; //位權重 while (n > 0){ int sh = n / 3; //商 if (n % 3 == 1) { char arr[1024] = { 0 }; strcpy(arr, p); memset(p, 0, 1024); strcat(p, "+"); char arr1[1024] = { 0 }; _itoa(q, arr1, 10); //其實這裡無需轉成十進位制,只是需要把權數轉為字串形式而已!!! strcat(p, arr1); strcat(p, arr); } if (n % 3 == 2) { sh++; char arr[1024] = { 0 }; strcpy(arr, p); memset(p, 0, 1024); strcat(p, "-"); char arr1[1024] = { 0 }; _itoa(q, arr1, 10); strcat(p, arr1); strcat(p, arr); } n = sh; q *= 3; } return p+1; } int main(){ int i; for (i = 1; i < 100; i++) { char*p = f2(i); printf("%d : %s\n", i, p); } return 0; }
學到的點:
三進位制列舉變相長除法轉化為+-表示式。
數字轉成字串(覆蓋儲存於字元陣列中)可以用itoa的十進位制
strcpy(a,b)是把b字元陣列直接覆蓋複製給a字元陣列,strcat(a,b)是a之後接上b