日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

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

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

轉載自:http://blog.sina.com.cn/s/blog_7571423b01016707.html

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

分析:

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

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標示未選擇該數字 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時,找到一個組合,輸出 15: myDump(aux, n); 16: 17:?// 遞歸結束條件:dest=0,說明找到一個組合;dest<0,說明該組合不滿足(和大于m); 18:?// 如果idx=n,則說明已達到規定的最大數字(范圍為1-n) 19:?if?(dest <= 0 || idx==n) 20:?return; 21: 22: helper(dest, idx+1, aux, n); 23: aux[idx] = 1;?// 標示選擇了數字idx+1 24: 25:?//因為已經選擇了idx,即選擇了數字idx+1,所以將m減去idx+1 26: helper(dest-idx-1, idx+1, aux, n); 27: aux[idx] = 0;?//無論結果是否滿足,都需要取消原來已選擇的數字idx+1,然后嘗試另一種組合 28: } 29: 30:?void?findCombination(int?n,?int?m) 31: { 32:?if(n>m)?//因為和為m,所以大于m的數肯定不行 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: }

?

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

?解題思路:
????顯而易見, 當n>m時, 肯定存在滿足題目要求的子集. 由于數列1,2,...,n是正整數數列, 這使得所有的大于m的數加上數列最小元素1都會大于m, 所以當n>m時我們只需要考慮子數列1,2,...,m即可.
?????當n<=m時,我們需要搜索1,2,...,n中符合條件的子集. 實際上, 我們可以將原問題分解成兩個子問題:
子問題一: 在n個數的數列,我們取n, 然后原問題就變為找出1,2,...,n-1中和為m-n的所有子集,然后將所有的子集都加上元素n就得到了原問題的部分解集;
子問題二: 我們不取n, 原問題就變為找出1,2,...,n-1中和為m的所有子集.
聯合兩個子問題的解, 便得到了原問題的解集.

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

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

?

?

#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;
}

總結

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

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