以AcWing1362为例
1.二进制法
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N = 35;
int need[N], food[N][N], sum[N];
int n, m;
int main()
{
cin >> n;
for(int i = 0; i < n; i ++)cin >> need[i];
cin >> m;
for(int i = 0; i < m; i ++)
for(int j = 0; j < n; j ++)
cin >> food[i][j];
vector<int> res;
for(int i = 0; i < 1<<m; i ++)
{
vector<int> t;
memset(sum, 0, sizeof sum);
for(int j = 0; j < m; j ++)
{
if(i>>j&1)
{
t.push_back(j);
for(int k = 0; k < n; k ++)
sum[k] += food[j][k];
}
}
bool flag = true;
for(int j = 0; j < n; j ++)
if(sum[j] < need[j])
flag = false;
if(flag)
if(res.empty() || res.size() > t.size() || res.size() == t.size() && t < res)
res = t;
}
cout << res.size() << ' ';
for(int i = 0; i < res.size(); i ++) cout << res[i] + 1 <<' ';
}
2.DFS法
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N = 30;
int need[N], food[N][N], sum[N];
vector<int> res, t;
int n, m;
bool check()
{
memset(sum, 0, sizeof sum);
for(auto item : t)
for(int i = 0; i < n; i ++)
sum[i] += food[item][i];
for(int i = 0; i < n; i ++)
if(sum[i] < need[i])
return false;
return true;
}
bool cmp()
{
if(res.empty() || res.size() > t.size() || res.size() == t.size() && res > t)
return true;
return false;
}
void dfs(int u)
{
if(u == m)
{
if(check() && cmp())
res = t;
return ;
}
//先不选
dfs(u+1);
//选一个
t.push_back(u);
dfs(u+1);
//恢复现场
t.pop_back();
}
int main()
{
cin >> n;
for(int i = 0; i < n; i ++)cin >> need[i];
cin >> m;
for(int i = 0; i < m; i ++)
for(int j = 0; j < n; j ++)
cin >> food[i][j];
dfs(0);
cout << res.size() << ' ';
for(auto item : res) cout << item + 1 << ' ';
return 0;
}
选多个DFS,以LeetCode39为例
class Solution {
public:
vector<vector<int>> ans;
vector<int> path;
vector<vector<int>> combinationSum(vector<int>& c, int target) {
dfs(c, 0, target);
return ans;
}
void dfs(vector<int>& c, int u, int target) {
if (target == 0) {
ans.push_back(path);
return;
}
if (u == c.size()) return;
//先选0个,直到不能选为止
for (int i = 0; c[u] * i <= target; i ++ ) {
dfs(c, u + 1, target - c[u] * i);
path.push_back(c[u]);
}
//恢复现场
for (int i = 0; c[u] * i <= target; i ++ ) {
path.pop_back();
}
}
};