網格-遞歸作業 集合里的乘法


描述
給定整數集合S和一個目標數T,判斷是否可以從S中挑選一個非空子集,子集中的數相乘的乘積為T。
 
關於輸入
輸入為兩行。
第一行為目標數T和S中的元素個數N,以空格隔開。
第二行為S中的N個元素,以空格隔開。
其中 N <= 16。
 
關於輸出
如果可以,則輸出YES,否則輸出NO。
 
例子輸入
Sample Input 1:

12 5
1 2 3 4 5

Sample Input 2:
33 5
4 2 8 7 5
例子輸出
Sample Output 1:

YES

Sample Output 2:
NO

 

代碼:

 1 //集合里的乘法 
 2 // 3 //2019-11-11 
 4 #include<iostream>
 5 #include<algorithm>
 6 using namespace std;
 7 int a[20];
 8 //涉及到除法就要考慮0的特判 
 9 bool mult(int num, int k, int n){ //試到第k個數.要用乘法湊出num, 一共n個數 
10     if(num==a[k]) return true;  
11     if(a[k]==0) return false; //一定要注意 
12     if(k+1<=n){
13         if(num%a[k]==0){
14             if(mult(num/a[k],k+1,n)) //取當前數 
15                 return true;
16             else
17                 return mult(num,k+1,n); //不取當前數 
18         }
19         else
20             return mult(num,k+1,n); //不取當前數         
21     }        
22     return false;
23 } 
24 int main(){
25     int t, n;
26     cin>>t>>n;
27     for(int i = 1; i <= n; i++)
28         cin>>a[i];
29     if(mult(t,1,n))
30         cout<<"YES"<<endl;
31     else
32         cout<<"NO"<<endl; 
33     return 0;
34 }

備注:

感覺自己這個回溯寫的挺亂的。關鍵在於拆分子問題。用遞歸來暴力枚舉每一個書取或不取。但因為我用的是除法,一定要注意除數不能為0,但如果用直接暴力乘的話就沒有這個問題。

我的代碼寫的太差了,補一個作業范例,思路就超級清晰:

 

 1 #include <iostream>
 2 using namespace std;
 3 int e[50],found=0,t,card;//數組 e 記錄集合中的元素,found 記錄是否已經找到子集
 4 void attempt(int i, int k)
 5 {
 6      if (found || i>card) return;
 7      if (k==t)
 8      {
 9          cout << "YES"; found=1; return;
10      }
11      attempt(i+1, k);//子集中不包含這個數
12      attempt(i+1, k*e[i]);//子集中包含這個數
13 }
14 int main()
15 {
16      cin >> t >> card;
17      for (int i=1; i<=card; i++) cin >> e[i];
18      attempt(1,1);
19      if (!found) cout << "NO";//如果沒找到就輸出 NO
20      return 0;
21 }    

 


免責聲明!

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



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