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