24點C++程序實現 編程之美1.16


解法1,對於任意輸入的四個數字,給出一個24點的解法,若無解,則沒有輸出。

 

原理參照下圖(編程之美原書)

 

 

 

代碼如下,僅供參考

// 1.16.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include<string>
#include "stdio.h"
#include <math.h> 
using namespace std;

const int CardsNumber = 4;//24點有四張卡
const double ErrorThreshold=1E-6;//由於舍入誤差,需要加入一個誤差閾值,誤差在一定范圍之內為,判斷相等
const int ResultValue = 24;

#define N 4

 
string result[CardsNumber]={"3","1","3","4"};
double number[CardsNumber]={3,1,3,4};
bool PointsGame(int n)
{
    if(n == 1)
    {
        //如果結果為24
        //由於舍入誤差,應允許一定范圍內的誤差

        if( fabs(number[0]-ResultValue)<ErrorThreshold)
        {
            cout<<result[0]<<endl;
            //cout<<'1'<<endl;
            return true;
        }
        else
        {
            return false;
        }

    }

    
    for(int i=0 ;i<n ;i++)
    {
        for(int j=i+1;j<n;j++)
        {
            double a,b;
            string expa,expb;

            a=number[i];
            b=number[j];
            number[j]=number[n-1];

            expa=result[i];
            expb=result[j];
            result[j]=result[n-1];

            result[i]='('+ expa +'+'+expb+')';
            number[i]=a+b;
            if(PointsGame(n-1))
                return true;

            result[i]='('+ expa +'-' + expb +')';
            number[i]=a-b;
            if(PointsGame(n-1))
                return true;

            result[i]='('+ expa + '*' + expb +')';
            number[i]=a*b;
            if(PointsGame(n-1))
                return true;

            if(b!=0)
            {result[i]='('+expa +'/'+ expb +')';
            number[i]=a/b;
            if(PointsGame(n-1))
                return true;

            }

            number[i]=a;
            number[j]=b;
            result[i]=expa;
            result[j]=expb;

        }
    }

    return false;
}




int _tmain(int argc, _TCHAR* argv[])
{


    
    PointsGame(4);




    return 0;
}

 

 

 

解法2,可以返回,輸入4個數字的情況下,一共有多少不同的解。

原理如下圖(編程之美原書)

 

 

書中沒有給出代碼,分享下我的代碼:

 

// 1.16.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include<string>
#include "stdio.h"
#include <math.h> 
using namespace std;

const int CardsNumber = 4;
const double ErrorThreshold=1E-6;
const int ResultValue = 24;

#define N 4

 



class doubleSet//以double數字為內容的集合
{
public:

    doubleSet()
    {
        
        length=0;
    }
    
    doubleSet(double p[],int n)
    {
        length=n;

        for(int i=0;i<n;i++)
        {
            content[i]=p[i];
        }
        
    }
    
    
    bool IsEmpty()
    {
        if(length==0 || length>65535)
            return true;
        else
            return false;
    }


    void Display()//顯示該集合
    {
        
        //content[length]='\0';
        for(int i=0;i<length;i++)
            printf("%f     ",content[i]);        
        for(int i=0;i<length;i++)
            cout<<content[i]<<endl;

        
    }

    int GetLength()
    {
        return length;
    }

    double* Getcontent()
    {
        return content;
    }


    static doubleSet Union(doubleSet set1,doubleSet set2)  //兩個集合求交集
    {
        int num1=set1.length;
        int num2=set2.length;

        if(num1==0)
            return set2;
        else if(num2==0)
            return set1;

        double *p1=set1.content;
        double *p2=set2.content;

        
        
        bool Repeat=0;
        for(int i=0;i<num2;i++)
        {
            
            for(int j=0;j<num1;j++)
            {
                if( *(p2+i)==*(p1+j))
                {
                    Repeat=1;
                    break;
                }
            }
            if(Repeat==1)
            {
                Repeat=0;
            }
            else
            {
            
            num1++;
            *(p1+num1-1)=*(p2+i);
            }
        }

        set1.length=num1;

        for(int i=0;i<num1;i++)
            set1.content[i]=p1[i];

        return set1;
    }

private:
    int length;//length表示集合的長度
    double content[500];//content代表集合中的內容
};

doubleSet fun(int i);
doubleSet S[16];  //定義16個double數字集合


int Mycheck( doubleSet set)//check   最后有多少個結果為24
{
    int num=0;
    double *content=set.Getcontent();
    for(int i=0;i<set.GetLength();i++)
    {
        if(fabs(content[i]-ResultValue)<ErrorThreshold)
        {
            num++;
        }
    }
    cout<<num<<endl;
    return num;

}
doubleSet Fork(doubleSet set1,doubleSet set2)//通過加減乘除合並兩個數字集合為一個數字集合
{

    
    if(set2.IsEmpty())
        return set1;

     if(set1.IsEmpty())
        return set2;


    doubleSet ret;
    int retLen=0;
     double RetContent[500];//因為函數結束后,會釋放局部變量,所以設置為靜態的
    //切記不要返回局部變量指着。
    
    double *content1=set1.Getcontent();
    double *content2=set2.Getcontent();

    for(int i=0;i<set1.GetLength();i++)
    {
        for(int j=0;j<set2.GetLength();j++)
        {
            *(RetContent+retLen++)=content1[i]+content2[j];
            *(RetContent+retLen++)=content1[i]-content2[j];
            *(RetContent+retLen++)=content2[j]-content1[i];
            *(RetContent+retLen++)=content1[i]*content2[j];
            if(content2[j]!=0)
                *(RetContent+retLen++)=content1[i]/content2[j];
            if(content1[i]!=0)
                *(RetContent+retLen++)=content2[j]/content1[i];

            
        }
    }
    
    return doubleSet(RetContent,retLen);
}


void TheGame(doubleSet set)
{
    //把i化為 2進制的數,第j位數為1的代表出現第j個數。
    int n=set.GetLength();

    //for(int i=1;i<=pow(2,n);i++)
    double *content1=    set.Getcontent();


    static double temp[4][1];
    for(int i=0;i<n;i++)//先構造2的指數倍
    {
         temp[i][0] = content1[i];
        S[static_cast<int>(pow(2.0,i))]=doubleSet(temp[i],1);
    }
    for(int i=1;i<=pow(2.0,n)-1;i++)
        S[i]=fun(i);//fun返回該集合數字,通過四則運算可以返回的所有結果

    Mycheck( S[static_cast<int>  (pow(2.0,n)-1)  ] );
}

doubleSet fun(int i)
{
    if(!S[i].IsEmpty())
        return S[i];

    for(int x=1;x<i;x++)
    {
        if((x&i)==x)
            S[i]=doubleSet::Union(S[i],Fork(fun(x),fun(i-x)));
    }
    return S[i];
}

int _tmain(int argc, _TCHAR* argv[])
{


    
    double a[4]={3,6,3,4};

    

    doubleSet set1=doubleSet(a,4);

    TheGame(set1);



    return 0;
}

 

 

 

 

注:本文主要參考編程之美,1.16節給出的理論,主要目的是把代碼貼出來給大家分享

本文的圖都來自《編程之美》

 

 


本人水平有限,懷着分享學習的態度發表此文,歡迎大家批評,交流。感謝您的閱讀。
歡迎轉載本文,轉載時請附上本文地址:http://www.cnblogs.com/Dzhouqi/p/3362259.html
另外:歡迎訪問我的博客 http://www.cnblogs.com/Dzhouqi/

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM