日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

【编程之美】24点游戏

發布時間:2025/3/21 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【编程之美】24点游戏 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自:http://blog.csdn.net/tianshuai1111/article/details/7713640

一,概述

? ? ? ? 二十四點是一種益智游戲,它能在游戲中鍛煉人們的心算,它往往要求人們將四個數字進行加減乘除(允許使用括號)求得二十四。然后將四個數字的計算公式表示出來。


二,中綴表達式求解

? ? ? ? ?最直接的方法就是采用窮舉法,游戲中可用的運算符只有四種,四個數字每個只能使用一次。

? ? ? ? ?1)不考慮括號情況

? ? ? ? ? ? ? ? 4個數全排列:4!=24種

? ? ? ? ? ? ? ? 需要三個運算符,且運算符可以重復:4*4*4=64

? ? ? ? ? ? ? ? 總計:1536

? ? ? ? ?2)考慮括號(是個難點)

? ? ? ? ? ? ? ? 自己想的加括號:四個數有五種加括號方式: ?(AB)CD ?、?AB(CD)、?A(BC)D 、?A((BC)D) 、?(AB)(CD)、A(B(CD))

? ? ? ? ? ? ? ? ?錯誤點:這里添加括號的時候,需要把四個數都看成相乘。需要加兩個括號來列舉比較直觀

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??AB(CD) ?= ??(AB)(CD)

? ? ? ? ? ? ? ? ?改正后:((AB)C)D ?、?(AB)(CD)?、 (A(BC))D 、?A((BC)D) 、A(B(CD))

? ? ? ? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? 四個運算數五種不同加括號方式的由來。這是一個經典的Catalan數問題。

? ? ? ? ? ? ? ? 這個經典Catalan數問題在組合數學教材上都能找到。原題目是:n 個數相乘, 不改變它們的位置, 只用括號表示不同的相乘順序,令g(n)表示這種條件下構成不同乘積的方法數,令C(n)表示第n個Catalan數。則有g(n)=C(n-1)。前幾個Catalan數為:C(0)=1,C(1)=1,C(2)=2,C(3)=5,C(4)=14,C(5)=42。所以g(4)=C(3)=5。

? ? ? ? ? ? ? ? 根據Catalan數的計算公式,有g(4)=g(1)g(3)+g(2)g(2)+g(3)g(1)。

? ? ? ? ? ? ? ? Catalan數的計算公式也同時提供了構造答案的方法。對于4個數,中間有3個位置,可以在任何一個位置一分為二,被分開的兩半各自的加括號方案再拼湊起來就得到一種4個數的加括號方案:

一個數時:(A),一種

兩個數:g(2)=g(1)g(1),所以是(A)(B)=(AB),一種

三個數:g(3)=g(1)g(2)+g(2)g(1)=(A)(BC)+(AB)(C),兩種

四個數:g(4)=g(1)g(3)+g(2)g(2)+g(3)g(1)

????????????? ?? =(A)[(B)(CD)+(BC)(D)]+(AB)(CD)+[(A)(BC)+(AB)(C)](D)

????????????? ?? =A(B(CD)) + A((BC)D) + (AB)(CD) + (A(BC))D + ((AB)C)D

? ? ? ? ?共有五種。于是寫代碼枚舉這五種加括號的方式即可。這種方法只是一種能得到正確答案的方法,擴展性和效率都極差。而且生成的表達式中也有冗余括號。


[html]?view plaincopy
  • #include?<iostream>??
  • #include?<cmath>??
  • using?namespace?std;??
  • ??
  • const?double?Threshold?=?1E-6;??
  • const?int?CardsNumber?=?4;??
  • const?int?ResultValue?=?24;??
  • double?number[CardsNumber];??
  • string?result[CardsNumber];??
  • ??
  • bool?PointsGame(int?n)??
  • {??
  • ?????if(n?==?1)??
  • ?????{??
  • ??????????//?由于浮點數運算會有精度誤差,所以用一個很小的數1E-6來做容差值??
  • ??????????//?本書2.6節中討論了如何將浮點數轉化為分數的問題??
  • ??????????if(fabs(number[0]?-?ResultValue)?<?Threshold)//結果等于24??
  • ??????????{??
  • ???????????????cout?<<?result[0]?<<?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]?=?'('?+?expb?+?'-'?+?expa?+?')';??
  • ???????????????number[i]?=?b?-?a;??
  • ???????????????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;??
  • ???????????????}??
  • ???????????????if(a?!=?0)??
  • ???????????????{??
  • ????????????????????result[i]?=?'('?+?expb?+?'/'?+?expa?+?')';??
  • ????????????????????number[i]?=?b?/?a;??
  • ????????????????????if(PointsGame(n?-?1))??
  • ?????????????????????????return?true;??
  • ???????????????}??
  • ??
  • ???????????????number[i]?=?a;//將本次循環的結果消除,繼續測試下一對數??
  • ???????????????number[j]?=?b;??
  • ???????????????result[i]?=?expa;??
  • ???????????????result[j]?=?expb;??
  • ??????????}??
  • ?????}??
  • ?????return?false;??
  • }??
  • ??
  • int?main()??
  • {??
  • ????int?x;??
  • ????for(int?i?=?0;?i?<?CardsNumber;?i++)??
  • ????{??
  • ?????????char?buffer[20];??
  • ?????????cout?<<?"the?"?<<?i?<<?"th?number:";??
  • ?????????cin?>>?x;??
  • ?????????number[i]?=?x;??
  • ?????????itoa(x,?buffer,?10);??
  • ?????????result[i]?=?buffer;??
  • ????}??
  • ????if(PointsGame(CardsNumber))??
  • ????{??
  • ?????????cout?<<?"Success."?<<?endl;??
  • ????}??
  • ????else??
  • ????{??
  • ?????????cout?<<?"Fail."?<<?endl;??
  • ????}??
  • }??

  • 三,分支限界法求解


    [html]?view plaincopy
  • #include?<iostream>??
  • #include?<set>??
  • #include?<string>??
  • #include?<cmath>??
  • using?namespace?std;??
  • ??
  • #define?N???4???//?4張牌,可變??
  • #define?RES?24??//?運算結果為24,可變??
  • #define?EPS?1e-6??
  • ??
  • struct?Elem??
  • {??
  • ????Elem(double?r,?string&?i):res(r),info(i){}??
  • ????Elem(double?r,?char*?i):res(r),info(i){}??
  • ????double?res;?//?運算出的數據??
  • ????string?info;?//?運算的過程??
  • ????bool?operator<(const?Elem&?e)?const??
  • ????{??
  • ????????return?res?<?e.res;?//?在set的紅黑樹插入操作中需要用到比較操作??
  • ????}??
  • };??
  • ??
  • int?A[N];???//?記錄N個數據??
  • //?用二進制數來表示集合和子集的概念,0110表示集合包含第2,3個數??
  • set<Elem>?vset[1<<N];???//?包含4個元素的集合共有16個子集0-15??
  • ??
  • set<Elem>&?Fork(int?m)??
  • {??
  • ????//?memo遞歸??
  • ????if?(vset[m].size())??
  • ????{??
  • ????????return?vset[m];??
  • ????}??
  • ????for?(int?i=1;?i<=m/2;?i++)??
  • ????????if?((i&m)?==?i)??
  • ????????{??
  • ????????????set<Elem>&?s1?=?Fork(i);??
  • ????????????set<Elem>&?s2?=?Fork(m-i);??
  • ????????????set<Elem>::iterator?cit1;??
  • ????????????set<Elem>::iterator?cit2;??
  • ????????????//?得到兩個子集合的笛卡爾積,并對結果集合的元素對進行6種運算??
  • ????????????for?(cit1=s1.begin();?cit1!=s1.end();?cit1++)??
  • ????????????????for?(cit2=s2.begin();?cit2!=s2.end();?cit2++)??
  • ????????????????{??
  • ????????????????????string?str;??
  • ????????????????????str?=?"("+cit1->info+"+"+cit2->info+")";??
  • ????????????????????vset[m].insert(Elem(cit1->res+cit2->res,str));??
  • ????????????????????str?=?"("+cit1->info+"-"+cit2->info+")";??
  • ????????????????????vset[m].insert(Elem(cit1->res-cit2->res,str));??
  • ????????????????????str?=?"("+cit2->info+"-"+cit1->info+")";;??
  • ????????????????????vset[m].insert(Elem(cit2->res-cit1->res,str));??
  • ????????????????????str?=?"("+cit1->info+"*"+cit2->info+")";??
  • ????????????????????vset[m].insert(Elem(cit1->res*cit2->res,str));??
  • ????????????????????if?(abs(cit2->res)>EPS)???
  • ????????????????????{??
  • ????????????????????????str?=?"("+cit1->info+"/"+cit2->info+")";??
  • ????????????????????????vset[m].insert(Elem(cit1->res/cit2->res,str));??
  • ????????????????????}??
  • ????????????????????if?(abs(cit1->res)>EPS)??
  • ????????????????????{??
  • ????????????????????????str?=?"("+cit2->info+"/"+cit1->info+")";??
  • ????????????????????????vset[m].insert(Elem(cit2->res/cit1->res,str));??
  • ????????????????????}??
  • ????????????????}??
  • ????????}??
  • ????return?vset[m];??
  • }??
  • ??
  • int?main()??
  • {??
  • ????int?i;??
  • ????for?(i=0;?i<N;?i++)??
  • ????????cin?>>?A[i];??
  • ????//?遞歸的結束條件??
  • ????for?(i=0;?i<N;?i++)??
  • ????{??
  • ????????char?str[10];??
  • ????????sprintf(str,"%d",A[i]);??
  • ????????vset[1<<i].insert(Elem(A[i],str));??
  • ????}??
  • ????Fork((1<<N)-1);//開始1111?表示四個數???
  • ????//?顯示算出24點的運算過程??
  • ????set<Elem>::iterator?it;??
  • ????for?(it=vset[(1<<N)-1].begin();???
  • ???????it!=vset[(1<<N)-1].end();?it++)??
  • ????????{??
  • ????????????if?(abs(it->res-RES)?<?EPS)??
  • ????????????????cout?<<?it->info?<<?endl;??
  • ????}??
  • } ?
  • 總結

    以上是生活随笔為你收集整理的【编程之美】24点游戏的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。