1. 程式人生 > >倒推法解決“四人玩火柴棍遊戲,每一次都是三個人贏,一個人輸”問題

倒推法解決“四人玩火柴棍遊戲,每一次都是三個人贏,一個人輸”問題

問題四人玩火柴棍遊戲,每一次都是三個人贏,一個人輸。輸的人要按贏者手中的火柴數進行賠償,即贏者手中有多少根火柴棍,輸者就賠償多少根。現知道玩過四次後,每人恰好輸過一次, 而且每人手中都正好有16根火柴。問此四人做遊戲前手中各有多少根火柴? 程式設計解決此問題。

這個問題是一道C++的程式設計入門題目,如果按正推來解決此問題的話。思路:設四個人的初始火柴棍分別為a,b,c,d.然後對其進行窮舉,最後找到滿足題意條件的一組值。這種方法的好處是比較簡單,但是程式的執行效率可能不是太好,而且程式碼也比較複雜。

     如果用倒推的方法解決這個問題,則會變的非常簡單。思路如下:

     我們知道最後每人手中的火柴棍都是16根,我們假設從第一個人開始,第一個人輸第一輪...第四個人輸第四輪。

     我們設倒數第一輪時每個人手中的火柴棍分別為a,b,c,d.此時是第四個人輸,其他人贏。

 a    b    c    d     (第四輪)

2a    2b    2c    d+a+b+c   (最後)

    有上可知,因為最後的時候每人手中的火柴棍數量相同,所以2a=2b=2c,則a=b=c

    我們設倒數第一輪時每個人手中的火柴棍分別為a1,b1,c1,d1,此時該是第三個輸,其他人贏。

 a1    b1    c1    d1     (第三輪)

                                         2a1    2b1    c1-a1-b1-d1    2d1( 這是按規則計算出來的第四輪結果)

a    b    c    d   (第四輪)

此時可知,2a1=a,2b1=b,2d1=d.因此上式可以改寫成:

 a/2    b/2    c+a/2+b/2+c/2    d/2     (第三輪)

a    b    c    d   (第四輪)

有上面的推斷我們可以知道:

 a/2    b/2    c+a/2+b/2+c/2    d/2     (第三輪)

 a    b    c    d     (第四輪)

2a    2b    2c    d+a+b+c   (最後)

由此我們可以得知,如果用倒推法來解決此問題的話,我們可以想象這個問題的逆問題:我們初始化剛開始時每人手中有16根火柴棍,而且每輪都是三個人輸,一個人贏,每個輸的人都需要把自己火柴棍的一半給贏的人。經過四輪這樣的比賽,我們求四輪之後每個人手中的火柴棍的數量。

這個即是原問題的逆問題。此問題求得的最後每個人手中火柴棍的數量即為原問題的解。

採用這個思路的話,可以很容易的用非常簡單的程式碼來解決這個問題。程式碼如下:

#include<iostream>
using namespace std;
void main()
{

	int a[4]={16,16,16,16};
	for(int i=0;i<4;i++)
	{
		for(int j=0;j<4;j++)
		{
			if(j==i)
				continue;
			a[i]+=a[j]/2;
			a[j]=a[j]/2;

		}
	}
	for(int i=0;i<4;i++)
	{
		cout<<a[i]<<endl;
	}

}