破碎的砝碼問題

2021-10-20 15:23:06 字數 3529 閱讀 5463

法國數學家梅齊亞克在它的《數學組合遊戲》中提出了這樣乙個問題:乙個商人有乙個重量為40磅的砝碼,有一天他不小心將該砝碼摔成了4塊。商人發現每塊砝碼的重量都是整磅數,而且每塊砝碼的重量各不相同,並且發現這四塊砝碼碎片可以在天平上稱出1~40磅之間的任意重量(整磅數)。問這四塊砝碼碎片的重量各是多少?

1、四塊砝碼重量加起來等於40磅

2、每塊砝碼的重量各不相同

3、四塊砝碼碎片可以在天平上稱出1~40磅之間的任意重量(整磅數)

由此可知:問題的求解空間是有限的、可列的,使用窮舉法是一種比較簡便的方法。

演算法描述:

repeat:窮舉組合,其中a,b,c,d互不相等,並且a+b+c+d=40;

if 組合可以在天平上稱出1

~40磅之間的任意重量(整磅數)

then 輸出該組合方式(答案),返回

else 繼續進行窮舉操作

until:窮舉完畢

現在需要解決兩個問題:

一、如何窮舉組合,a,b,c,d互不相等,且a+b+c+d=40?

對於該問題,我們可能很快可以寫出如下的程式:

for

(int i =

1; i <40;

++i)

for(

int j =

1; j <40;

++j)

for(

int k =

1; k <40;

++k)

for(

int s =

1; s <40;

++s)

,為該題的可能解

}

這樣的演算法低效且冗餘。

1、會對很多i,j,k,s相等的情況進行遍歷

2、這裡的組合是不考慮排列方式的組合,即組合與組合其實質是一樣的。

故推薦使用如下優化的演算法:

for

(int i =

1; i <=40;

++i)

for(

int j = i+

1; j <=

40-i;

++j)

for(

int k = j+

1; k <=

40-i-j;

++k)

for(

int s = k+

1; s <=

40-i-j-k;

++s)

if(i+j+k+s ==40)

得到乙個組合,為該題的可能解

該演算法確保內層迴圈搜尋範圍小於外層迴圈搜尋範圍,這樣每次得到的組合方式的4個元素都不會相等,且不會出現「相同組合、不同排列」的情況。

二、如何判斷組合可以在天平上稱出1~40磅之間的任意重量(整磅數)?

如果將其形式化為數學符號,它其實就是要判斷方程:

x 1a

i+x2

bi+x

3ci+

x4di

=wx1

,x2,

x3,x

4∈

x_1a_i+x_2b_i+x_3c_i+x_4d_i=w \ \ \ \ \ x_1,x_2,x_3,x_4\in \

x1​ai​

+x2​

bi​+

x3​c

i​+x

4​di

​=wx

1​,x

2​,x

3​,x

4​∈在w=1,2,3…40時是否都有解。解空間限定在上。

例如:假設有這樣乙個解=使得方程

x 1a

i+x2

bi+x

3ci+

x4di

=1

x_1a_i+x_2b_i+x_3c_i+x_4d_i=1

x1​ai​

+x2​

bi​+

x3​c

i​+x

4​di

​=1有解,即

1 ×a

i+0×

bi−1

×ci+

1×di

=1⇒a

i+di

=ci+

11×a_i+0×b_i-1×c_i+1×d_i=1\\ \rightarrow a_i+d_i=c_i+1

1×ai​+

0×bi

​−1×

ci​+

1×di

​=1⇒

ai​+

di​=

ci​+

1這樣天平的一邊放上碎片ai和di,另一邊放上碎片ci和乙個1磅的砝碼,天平就平衡了,這說明碎片可以稱出1磅的重量。

演算法描述如下:

int

justify

(int i,

int j,

int k,

int s)

是否可以稱出1~40磅之間的任意重量if(

!getweight

(i,j,k,s,weight)

)return0;

//不可以稱出1~40磅之間的任意重量

}return1;

//可以稱出1~40磅之間的任意重量

}

getweight演算法描述如下:

int

getweight

(int i,

int j,

int k,

int s,

int weight)

#include

"stdlib.h"

#include

using

namespace std;

intgetweight

(int i,

int j,

int k,

int s,

int weight)

intjustify

(int i,

int j,

int k,

int s)

是否可以稱出1~40磅之間的任意重量

return0;

//不可以稱出1~40磅之間的任意重量

return1;

//可以稱出1~40磅之間的任意重量

}void

pieces()

,為該題的可能解

cout << i <<

" "<< j <<

" "<< k <<

" "<< s << endl;

}int

main

(int argc,

char

* ar**)

//結果為:1 3 9 27

本題的關鍵在於

1、如何窮舉組合,使得a,b,c,d互不相等,且a+b+c+d=40;

2、如何判斷組合可以在天平上稱出1~40磅之間的任意重量(整磅數)。

解決了這兩個問題,就能得出問題的解。

破碎的砝碼問題

1.問題描述 一天商人不小心把40磅重的砝碼摔成4部分,發現4部分砝碼的重量都是整磅數,而且可以用它們稱出任意1 40之間的整數磅質量,問這四塊砝碼各重多少磅?2.該問題的數學分析 必須有1磅的砝碼,否則39磅的重量無法稱出.有了1磅的砝碼後,再加上乙個3磅的砝碼,可稱出2 4磅的重量.有了1磅和3...

C語言窮舉法解決破碎的砝碼

1.問題描述 一天商人不小心把40磅重的砝碼摔成4部分,發現4部分砝碼的重量都是整磅數,而且可以用它們稱出任意1 40之間的整數磅質量,問這四塊砝碼各重多少磅?2.該問題的數學分析 必須有1磅的砝碼,否則39磅的重量無法稱出.有了1磅的砝碼後,再加上乙個3磅的砝碼,可稱出2 4磅的重量.有了1磅和3...

稱砝碼問題

有一組砝碼,重量互不相等,分別為m1 m2 m3 mn 它們可取的最大數量分別為x1 x2 x3 xn 現要用這些砝碼去稱物體的重量 問能稱出多少種不同的重量。input 測試資料第一行乙個整數n n 10 表示有多種不同的砝碼 第二行n 個整數 中間用空格分隔 m1 m2 m3 mn 分別表示 n...