【C#】 迴圈小練習_天平秤物

窮舉法的問題實踐。

有4個砝碼,總重量40g ,砝碼的重量是整數,請找出4個砝碼在天平上秤重時,可以秤出1g ~ 40g 的重物。

所以要先找出這是4顆砝碼 {w1、w2、w3、w4}。
條件是
1.4顆加起來重量是40g
2.每一顆重量不相同。
3.可以利用這4顆砝碼秤出 1g ~ 40g的重物

因為天平是兩端。所以秤重量可以利用..
兩邊總和相等,例如:1 + 4 = 2 + W  這樣的排列就可以秤出W = 3 。
或是單邊等重,例如:1 + 4 =  W 這樣可以秤出 W = 5。
或是集中在單邊,例如:1 + 2 + 3 + 4 = W 這樣可以秤出 W = 10
因此要找出4顆可以秤出1g ~ 40g (W) 的重物都有解,
也就是W = w1 + w2 + w3 + w4  。 
這時再看看,當砝碼沒用上時。 例如上面案例W = 5 的,就只用了兩個砝碼
也有砝碼全部用在單邊,例如上面案例W = 10的。
也或者是當作減項的,例如上面案例W = 3的,就是利用 1 + 4 - 2(減項),來得到W = 3。

因此可以導出一個公式, 有用上(1)、沒用上(0)、當作減項 (-1)
W = w1*a1 + w2*a2 + w3*a3 + w4*a4 
其中 a1、a2、a3、a4 可能的值是 { 1、0、-1 }
只要最後能符合這個公式,那就算是找到這4顆砝碼了。 

之後在列出秤重的結果。
 

 static void Main(string[] args)
        {
            //窮舉法列出多種組合
            int flag;
            int x;
            int d1, d2, d3, d4;
            int w1 = 0, w2 = 0, w3 = 0, w4 = 0;
            
            #region 檢查砝碼
            for (int i = 1; i <= 40; i++)
            {
                for (int j = i + 1; j <= 40 - i; j++)//內圈起始值為外圈加1,這樣數字就不會重複計算。
                {
                    for (int k = j + 1; k <= 40 - i - j; k++)
                    {
                        int m = 0;
                        if ((m = 40 - i - j - k) >= k)
                        {

                            for (flag = 1, x = 1; x < 41 && flag == 1; x++)
                            {
                                //假如重物放天平左邊,法碼可放置在:-1:天平左邊(減項);1天平右邊;0不用該法碼
                                for (flag = 0, d1 = 1; d1 > -2; d1--)
                                {
                                    for (d2 = 1; d2 > -2 && flag == 0; d2--)
                                    {
                                        for (d3 = 1; d3 > -2 && flag == 0; d3--)
                                        {
                                            for (d4 = 1; d4 > -2 & flag == 0; d4--)
                                            {
                                                if (x == i * d1 + j * d2 + k * d3 + m * d4)
                                                {
                                                    flag = 1;
                                                }

                                            }
                                        }
                                    }
                                }
                            }
                            if (flag == 1)
                            {
                                Console.Write("砝碼重量為:{0} {1} {2} {3}", i, j, k, m);
                                Console.ReadLine();
                                w1 = i;
                                w2 = j;
                                w3 = k;
                                w4 = m;
                            }
                        }

                    }

                }

            }
            #endregion

            #region 處理秤重結果
            string left = "";
            string right = "";
            for (int i = 1; i <= 40; i++)
            {
                for (int a1 = -1; a1 <= 1; a1++)
                {
                    for (int a2 = -1; a2 <= 1; a2++)
                    {
                        for (int a3 = -1; a3 <= 1; a3++)
                        {
                            for (int a4 = -1; a4 <= 1; a4++)
                            {
                                if (i == a1 * w4 + a2 * w3 + a3 * w2 + a4 * w1)
                                {
                                    bool f = true;
                                    left = i + "";
                                    switch (a1)                             //依據狀態調整顯示算式
                                    {
                                        case -1:                            //狀態-1 等號左邊
                                            left = left + " + " + w4;
                                            break;
                                        case 1:                             //狀態1 等號右邊
                                            if (f)
                                            {
                                                right = right + w4;         //如果是第一項,數值不用有 + 號
                                            }
                                            else
                                            {
                                                right = right + " + " + w4;  //已經有數值之後都要+號
                                            }
                                            f = false;                      //已經有數值,標記變更為false
                                            break;
                                    }
                                    switch (a2)                             //依據狀態調整顯示算式
                                    {
                                        case -1:                            //狀態-1 等號左邊
                                            left = left + " + " + w3;
                                            break;
                                        case 1:                             //狀態1 等號右邊
                                            if (f)
                                            {
                                                right = right + w3;         //如果是第一項,數值不用有 + 號
                                            }
                                            else
                                            {
                                                right = right + " + " + w3;  //已經有數值之後都要+號
                                            }
                                            f = false;                      //已經有數值,標記變更為false
                                            break;
                                    }
                                    switch (a3)                             //依據狀態調整顯示算式
                                    {
                                        case -1:                            //狀態-1 等號左邊
                                            left = left + " + " + w2;
                                            break;
                                        case 1:                             //狀態1 等號右邊
                                            if (f)
                                            {
                                                right = right + w2;         //如果是第一項,數值不用有 + 號
                                            }
                                            else
                                            {
                                                right = right + " + " + w2;  //已經有數值之後都要+號
                                            }
                                            f = false;                      //已經有數值,標記變更為false
                                            break;
                                    }
                                    switch (a4)                             //依據狀態調整顯示算式
                                    {
                                        case -1:                            //狀態-1 等號左邊
                                            left = left + " + " + w1;
                                            break;
                                        case 1:                             //狀態1 等號右邊
                                            if (f)
                                            {
                                                right = right + w1;         //如果是第一項,數值不用有 + 號
                                            }
                                            else
                                            {
                                                right = right + " + " + w1;  //已經有數值之後都要+號
                                            }
                                            f = false;                      //已經有數值,標記變更為false
                                            break;
                                    }
                                    Console.WriteLine(left + " = " + right);

                                }
                                left = "";
                                right = "";
                            }
                        }
                    }
                }
            }
            #endregion

            Console.ReadLine();
        }
    }

 

水滴可成涓流,涓流可成湖泊大海。
汲取累積知識,將知識堆積成常識;將常識探究成學識;將學識簡化為知識;授人自省。