PAT甲級1068【Find More Coins】 dfs
阿新 • • 發佈:2019-02-12
先掛上題目連結~https://www.patest.cn/contests/pat-a-practise/1068
分析:給定多少錢,問能不能通過已有的硬幣組合湊成該整數,如果可以,輸出硬幣字典序最小的組合;否則輸出”No Solution“。此類組合問題我們當然是想到萬能的搜尋~推薦dfs,個人用的比較習慣。注意事項如下:
1、找字典序最小的一種思路是將硬幣按面值大小升序排序,這樣我們dfs搜出的第一種情況便是答案(可以仔細想想為什麼
2、如果就按上面的思路進行深搜會有幾個測試點超時TAT,剪枝則是求出第一種情況後,後續搜尋直接返回(通過設定標誌位判斷)。然而,即使是這樣在最後一個測試點還是會超時,一個原因是資料量比較大,很皮的是這個情況根本沒有solution,於是特判就好啦。求出所有硬幣的面值總和sum,如果sum<m,則直接輸出”No Solution“,於是問題就這樣解決了~
程式碼:
#include<bits/stdc++.h> using namespace std; const int maxn = 1e4+10; int coin[maxn]; int n,m; bool vis[maxn]={false}; bool flag = false,first=true; vector<int> ansPath; int k; void dfs(int cur, vector<int> path, int w){ if(flag) return; vis[cur] = true; if(w > m) return; if(w == m){ flag = true; if(first){ ansPath = path; first = false; } return; } for(int i = 1; i<=k; i++){ if(!vis[i]){ path.push_back(coin[i]); dfs(i, path, w+coin[i]); vis[i] = false; path.pop_back(); } } } int main(){ scanf("%d%d", &n, &m); long sum = 0; for(int i = 1; i<=n; i++){ scanf("%d", &coin[i]); sum += coin[i]; } if(sum < m) printf("No Solution"); else { sort(coin+1, coin+n+1); k = n; for(int i = 1; i<=n; i++) if(coin[i]>=m){ k = i; break; } dfs(0, ansPath, 0); if(flag){ printf("%d", ansPath[0]); for(int i = 1; i<ansPath.size(); i++) printf(" %d", ansPath[i]); } else printf("No Solution"); } return 0; }