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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

输入两个整数 n 和 m ,从数列 1 , 2 , 3.......n 中随意取几个数 ,使其和等于 m

發(fā)布時(shí)間:2023/12/4 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 输入两个整数 n 和 m ,从数列 1 , 2 , 3.......n 中随意取几个数 ,使其和等于 m 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)載自:http://blog.sina.com.cn/s/blog_7571423b01016707.html

編程求解:輸入兩個(gè)整數(shù) n 和 m ,從數(shù)列 1 , 2 , 3.......n 中隨意取幾個(gè)數(shù) ,使其和等于 m , 要求將其中所有的可能組合列出來(lái).

分析:

???????主要思想:分治,即m=idx+m-idx
???????從最大數(shù)字n開(kāi)始查找,然后逐漸后退,但每次查找只會(huì)在比當(dāng)前數(shù)字大的方向進(jìn)行組合嘗試,這樣可以保證找到的組合不會(huì)重復(fù)。
參考代碼

1: #include 2: #include 3: #include<<SPAN style="COLOR: #0000ff">string.h> 4:?void?myDump(int?aux[],?int?n) 5: { 6:?for?(int?i=0; i 7:?if?(aux[i])?// 0標(biāo)示未選擇該數(shù)字 8: printf("=", i+1); 9: printf("\n"); 10: } 11: 12:?void?helper(int?dest,?int?idx,?int?aux[],?int?n) 13: { 14:?if?(dest == 0)?// m減為0時(shí),找到一個(gè)組合,輸出 15: myDump(aux, n); 16: 17:?// 遞歸結(jié)束條件:dest=0,說(shuō)明找到一個(gè)組合;dest<0,說(shuō)明該組合不滿足(和大于m); 18:?// 如果idx=n,則說(shuō)明已達(dá)到規(guī)定的最大數(shù)字(范圍為1-n) 19:?if?(dest <= 0 || idx==n) 20:?return; 21: 22: helper(dest, idx+1, aux, n); 23: aux[idx] = 1;?// 標(biāo)示選擇了數(shù)字idx+1 24: 25:?//因?yàn)橐呀?jīng)選擇了idx,即選擇了數(shù)字idx+1,所以將m減去idx+1 26: helper(dest-idx-1, idx+1, aux, n); 27: aux[idx] = 0;?//無(wú)論結(jié)果是否滿足,都需要取消原來(lái)已選擇的數(shù)字idx+1,然后嘗試另一種組合 28: } 29: 30:?void?findCombination(int?n,?int?m) 31: { 32:?if(n>m)?//因?yàn)楹蜑閙,所以大于m的數(shù)肯定不行 33: n=m; 34: 35:?int* aux=new?int[n]; 36: memset(aux, 0, n*sizeof(int)); 37: 38: helper(m, 0, aux,n); 39: 40:?delete[] aux; 41: } 42: 43:?int?main() 44: { 45:?int?n,m; 46: scanf("%d,%d",&m,&n); 47: 48: findCombination(n,m); 49: 50: getchar(); 51:?return?0; 52: }

?

*****************************************************************************

?解題思路:
????顯而易見(jiàn), 當(dāng)n>m時(shí), 肯定存在滿足題目要求的子集. 由于數(shù)列1,2,...,n是正整數(shù)數(shù)列, 這使得所有的大于m的數(shù)加上數(shù)列最小元素1都會(huì)大于m, 所以當(dāng)n>m時(shí)我們只需要考慮子數(shù)列1,2,...,m即可.
?????當(dāng)n<=m時(shí),我們需要搜索1,2,...,n中符合條件的子集. 實(shí)際上, 我們可以將原問(wèn)題分解成兩個(gè)子問(wèn)題:
子問(wèn)題一: 在n個(gè)數(shù)的數(shù)列,我們?nèi), 然后原問(wèn)題就變?yōu)檎页?,2,...,n-1中和為m-n的所有子集,然后將所有的子集都加上元素n就得到了原問(wèn)題的部分解集;
子問(wèn)題二: 我們不取n, 原問(wèn)題就變?yōu)檎页?,2,...,n-1中和為m的所有子集.
聯(lián)合兩個(gè)子問(wèn)題的解, 便得到了原問(wèn)題的解集.

????我們用subsets( n, m) 表示原問(wèn)題, 那么原問(wèn)題可表示為子問(wèn)題 subsets(n-1, m) 和subsets( n-1, m-n)的解集的并集.
????即:???subsets( n, m)??= subsets(n-1, m) U subsets( n-1, m-n)
????實(shí)際中,可采用回溯的方法進(jìn)行求解. 后面附有完整的代碼.

????實(shí)際的搜索方法類似于二叉樹(shù)的方法, 去除不符合條件的解. 例如下面的二叉樹(shù)就表示了1,2,...,n的全組合的求解過(guò)程. 左邊分支表示取,右邊的分支表示舍. 針對(duì)于0-1背包問(wèn)題, 八皇后問(wèn)題, 射擊十次命中九十環(huán)的打法問(wèn)題等等, 則需要剪除掉一些不符合條件的子樹(shù).

?

?

#include <stdio.h>
#include <assert.h>
#include <time.h>

#define MAXN 1000



int stack[MAXN];
int top = -1;
void push( int e )
{
?assert( top < MAXN );
?stack[++top] = e;
}

void pop( )
{
?assert( top > -1 );
?top--;
}

void clear()
{
?top = -1;
}

void printStack( )
{
?int i=top;
?while( i>-1 )
??printf("%d\t", stack[i--] );
?printf("\n");
}


int subsets( int n, int m )
{
?int i;
?int num=0;
?int flag = 1;

?
?if( n > m )
??n = m;

?
?for( i = n; flag && i>=1; i-- )
?{
??
??push( i );
??
??
??if( m-i == 0 )
??{
???num++;
???printStack();
??}
??else
??{
???
???
???if( (i-1)*i/2 < (m-i) )
???{
????pop();
????flag = 0;
????continue;
???}

???
???num += subsets( i-1, m-i );
??}
??
??
??pop();
?}?

?return num;
}

void testSubsets()
{
?assert( 1 == subsets( 1, 1 ) );
?printf( "\n\n" );
?assert( 0 == subsets( 1, 2 ) );
?printf( "\n\n" );
?assert( 3 == subsets( 5, 6 ) );
?printf( "\n\n" );
?assert( 5 == subsets( 7, 7 ) );
}

int main()
{
?testSubsets( );

?clock_t start = clock();
?subsets( 50, 50 );
?clock_t duration = clock() - start;
?printf("it takes %d seconds\n", duration/CLOCKS_PER_SEC );
?return 0;
}

總結(jié)

以上是生活随笔為你收集整理的输入两个整数 n 和 m ,从数列 1 , 2 , 3.......n 中随意取几个数 ,使其和等于 m的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。