【搜索】數的划分


  廢話不多說,直接看題。

  首先先來說明一下題意:具體就是說一共要分成k個數,它們的和為n,看到這你們會想到什么,小編第一眼就會想到小學/學前班學的東西,把一個數拆成兩個數的和。如:

  

  就像這樣,只是情況有變,把一個數分成更多的數的和就OK了。

  行了,扯的遠了,回歸正題,既然這道題出現在搜索中,就用搜索吧(其實其它方法也可以,隔壁Willian用三重循環強行打過)。

  既然搜索,就先考慮一下用深搜還是廣搜,就用深搜把(個人偏愛),那怎么搜呢?舉個栗子以題目的栗子為栗,7怎么分?為了按順序,那么第一位先取1吧,接下來我們還有6要分,還剩下兩個數;第二位也取1吧,那么我們還有5要分,還剩下1個數的位置,於是我們就會發現還剩下一個數的位置,只能放5了,那么就方案數加1,返回。

  這樣整個搜索程序不就豁然開朗了嗎?放進去三個參數,分別是上一個數的值,剩余要分的數的個數與剩下要分的數值。

  此時我想你一定會有一個大大的問號吧,為什么要傳上一個數的值呢?因為按照之前的栗子,為了按順序來,是不是后面的數總會保持比前一個數大或者相等,這一點很容易理解,如果比之前的數小了,會出現重復(如1,1,5和5,1,1重復)的情況,正是如此,我們所要每一次填進去的數的范圍也會得到減小,抽象的來說就是這樣:前一個數<=本次所填的數<剩下要分的數值/數的個數(這是最不好理解的地方,此處的限制是為了防止前面的數過大,而后面的數連1都不能取,這樣可以有效的避免了這種情況,所以在邊界條件處不需要再進行判斷還能不能取,因為后面的數都會滿足這個關系式,所以后面的數最小都可以等於這個所填的數,所以剩下要分的數值/數的個數能保證后面的數大於或等於這個所填數),這樣程序就寫出來了(代碼比較簡單且上文有解釋,就不寫注釋了,原諒小編的手懶):

  

 1 #include<iostream>
 2 using namespace std;
 3 int n,k,a[10000],sum=0,ans;
 4 void dfs(int past,int cnt,int num)
 5 {
 6     if(cnt==1)
 7     {
 8         ans++;
 9         return;
10     }
11     for(int i=past;i<=num/cnt;i++)
12     dfs(i,cnt-1,num-i);
13 }
14 int main()
15 {
16     cin>>n>>k;
17     dfs(1,k,n);
18     cout<<ans;
19     return 0;
20 }


免責聲明!

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



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