1、零钱兑换
问题1:零钱兑换问题商店给用户兑换面值为W的金额,只能用零钱的组合兑换给客户,假设每种零钱的数量不限。输入说明:输入1:W输入2:零钱种类输入3:零钱面值输出说明:能兑换的零钱组合。
示例输入1:12 3 10 5 2 输出示例:10 2 5 5 2 2 2 2 2 2 2
输入示例2:18 3 10 4 2
1.1回溯法
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int w, n;
int m[20];
void dfsprint(const vector<int>& ans) {
for (int i = 0; i < ans.size(); i++) {
cout << ans[i];
i == ans.size() - 1 ? cout << endl : cout << " ";
}
}
void dfs(int sum, int index, vector<int>& ans) {
if (sum == w) {
dfsprint(ans);
return;
}
if (index >= n || sum > w) return;
ans.push_back(m[index]);
dfs(sum + m[index], index, ans); // 使用当前硬币
ans.pop_back();
dfs(sum, index + 1, ans); // 跳过当前硬币
}
int main() {
cin >> w >> n;
for (int i = 0; i < n; i++) cin >> m[i];
sort(m, m + n, greater<int>()); // 降序排序优化
vector<int> ans;
dfs(0, 0, ans);
}
1.2贪心法
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int w1, n;
cin >> w1 >> n;
vector<int> coins(n);
for (int i = 0; i < n; i++) cin >> coins[i];
sort(coins.rbegin(), coins.rend()); // 降序排序
while (!coins.empty()) {
int w = w1;
vector<int> ans;
for (int coin : coins) {
while (w >= coin) {
ans.push_back输入bash scripts/boot
w -= coin;
}
}
for (int i = 0; i < ans.size(); i++) {
cout << ans[i];
if (i != ans.size() - 1) cout << " ";
}
cout << endl;
coins.erase(coins.begin());
}
}
2、活动安排
示例输入1:3 1 4 1 3 3 5
示例输入2:10 1 3 2 4 3 5 2 8 4 6 3 7 2 8 2 3 3 4 5 6
2.1贪心法
#include <iostream>
#include<algorithm>
#include<vector>
using namespace std;
struct activity{
int number,begin,end;
};
bool cmp(activity a,activity b){
return a.end<b.end;
}
int main()
{
int n;
vector<activity> act;
vector<activity> ans;
cin>>n;
for(int i=0;i<n;i++){
activity t;
t.number=i+1;
cin>>t.begin>>t.end;
act.push_back(t);
}
sort(act.begin(),act.end(),cmp);
int time=act[0].end;
ans.push_back(act[0]);
for(int i=1;i<act.size();i++){
if(act[i].begin>=time){
ans.push_back(act[i]);
time=act[i].end;
}
}
for(auto p:ans)cout<<"选择活动"<<p.number<<":["<<p.begin<<","<<p.end<<")"<<endl;
}
2.2回溯法+剪枝
#include <iostream>
#include<algorithm>
#include<vector>
using namespace std;
struct activity {
int number, begin, end;
};
vector<activity> act;
vector<activity> best_ans;
int max_size = 0;
void dfs(int index, int time, vector<activity> ans) {
if (index == act.size()) {
if (ans.size() > max_size) { // 只保留最优解
best_ans = ans;
max_size = ans.size();
}
return;
}
// 剪枝:剩余活动全选也无法超越当前最优解时终止
if (ans.size() + (act.size() - index) <= max_size) return;
dfs(index + 1, time, ans);
ans.push_back(act[index]);
if (act[index].begin >= time) {
dfs(index + 1, act[index].end, ans);
}
}
int main()
{
int n;
vector<activity> ans;
cin >> n;
for (int i = 0; i < n; i++) {
activity t;
t.number = i + 1;
cin >> t.begin >> t.end;
act.push_back(t);
}
dfs(0, 0, ans);
for (auto p : best_ans) {
cout << "选择活动" << p.number << ":[" << p.begin << "," << p.end << ")" << endl;
}
}
2.3动态规划法
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//定义活动结构体:活动编号,开始时间,结束时间
struct activity {
int number, begin, end;
};
//排序表达式,定义依照活动的结束时间先后进行排序
bool cmp(activity a, activity b) {
return a.end < b.end;
}
void Solution(vector<activity>& acts, vector<int>& dp, vector<int>& p) {
vector<int> selected;
int i = dp.size() - 1;
while (i >= 0) {
if (p[i] == -1) {
if (dp[i] == 1) selected.push_back(i);
i--;
}
else if (dp[i] == dp[p[i]] + 1) {
selected.push_back(i);
i = p[i];
}
else {
i--;
}
}
reverse(selected.begin(), selected.end());
for (int idx : selected)cout << "选择活动" << acts[idx].number << ": [" << acts[idx].begin << "," << acts[idx].end << ")" << endl;
}
int main() {
int n;
cin >> n;
vector<activity> acts(n);
for (int i = 0; i < n; ++i) {
acts[i].number = i + 1;
cin >> acts[i].begin >> acts[i].end;
}
sort(acts.begin(), acts.end(), cmp);
vector<int> dp(n, 1),p(n, -1);
for (int i = 1; i < n; ++i) {
for (int j = i - 1; j >= 0; --j)if (acts[j].end <= acts[i].begin)p[i]= j;
if (p[i] != -1)dp[i] = max(dp[i - 1], dp[p[i]] + 1);
else dp[i] = max(dp[i - 1], 1);
}
Solution(acts, dp, p);
return 0;
}
627

被折叠的 条评论
为什么被折叠?



