C趣味程序百例(24)小明買書

字號:

76.小明買書
     小明假期同爸爸一起去書店,他選中了六本書,每本書的單價分別為:3.1,1.7,2,5.3,0.9和7.2。不巧的是,小明的爸爸只帶了十幾塊錢,為了讓小明過一個愉快的假期,爸爸扔然同意買書,但提郵購一個要求,要小明從六本書中選出若干本,使得單價相加所得的和同10最接近。你能夠幫助小明解決這個問題嗎?
    *問題分析與算法設(shè)計
     分析題意,可將題目簡化為:從六個數(shù)中選出若干個求和,使得和與10的差值最小。
     題目中隱含兩個問題,其一是怎樣從六個數(shù)中選出若干個數(shù);其二是求與10的差。
     從六個數(shù)中選出若干個數(shù)實(shí)質(zhì)是從六個數(shù)中選出若干個進(jìn)行組合。每個數(shù)在組合過程中只有兩種情況:要么是選中參加求和,要么是沒選中不參加求和。這樣就可以使用六重循環(huán)對每個數(shù)是否參加求和進(jìn)行全部可能情況的組合。
     關(guān)于求與10的差值應(yīng)當(dāng)注意的是:差值的含義是指差的絕對值。例如:“9-10=-1"和"11-10=1",但9和11這兩者與10的差值都是1。若認(rèn)為”9“與”10的差值為-1就錯了。
    *程序與程序注釋
    #include
    #include
    void main()
    {
     int d[6],m,i,j;
     long b[63],flag;
     float c[6],min,x;
     printf("Please enter the prices of 6 books:");
     for(i=0;i<6;i++) scanf("%f",&c[i]); /*輸入六個浮點(diǎn)數(shù)*/
     for(i=0,min=-1,d[0]=0;d[0]<2;d[0]++) /*建立六個數(shù)的全部組合并處理*/
     for(d[1]=0;d[1]<2;d[1]++) /*i:差值具有min組合的數(shù)量*/
     for(d[2]=0;d[2]<2;d[2]++) /*min:與10的最小差值*/
     for(d[3]=0;d[3]<2;d[3]++) /*d[]:組合時是否取該數(shù)的標(biāo)志*/
     for(d[4]=0;d[4]<2;d[4]++)
     for(d[5]=0;d[5]<2;d[5]++)
     {
     for(flag=0,x=0,j=5;j>=0;j--)
     /*flag:將六個數(shù)的組合用對應(yīng)的一個十進(jìn)制位表示 x:對應(yīng)六個數(shù)組合的和*/
     {
     x+=c[j]*d[j]; flag=flag*10+d[j];
     }
     x=((x-10>0)? x-10:10-x); /*x: 組合的和與10的差*/
     if(min<0)
     {
     min=x; /*對第一次計算出的差min進(jìn)行處理*/
     b[i++]=flag; /*b[]:有相同的min的flag的數(shù)組 i:b[]數(shù)組的下標(biāo)*/
     }
     else if(min-x>1.e-6) /*對新的min的處理*/
     {
     min=x; b[0]=flag; i=1;
     }
     else if(fabs((double)x-min)<1.e-6)
     b[i++]=flag; /*對相等min的處理*/
     }
     for(m=0;m     {
     printf("10(+ -)%.2f=",min);
     for(flag=b[m],j=0;flag>0;j++,flag/=10)
     if(flag%10) /*將b[]中存的標(biāo)記flag還原為各個數(shù)的組合*/
     if(flag>1) printf("%.2f+",c[j]);
     else printf("%.2f\n",c[j]);
     }
    }
    *運(yùn)行結(jié)果
     Please enter the prices of 6 books:3.1 1.7 2.0 5.3 0.9 7.2
     10(+ -)0.10=2.00+0.90+7.20
     10(+ -)0.10=1.70+2.00+5.30+0.90
     10(+ -)0.10=3.10+1.70+5.30
    *思考題
     可以看出,程序中求六個數(shù)所能產(chǎn)生全部組合的算法并不好,使用六重循環(huán)進(jìn)行處理使程序顯得不夠簡潔。可以設(shè)計出更通用、優(yōu)化的算法產(chǎn)生全部組合。