题目描述
文字描述
农民 John 以拥有世界上最健康的奶牛为傲。他知道每种饲料中所包含的牛所需的最低的维他命量是多少。请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少。
给出牛所需的最低的维他命量,输出喂给牛需要哪些种类的饲料,且所需的饲料剂量最少。
维他命量以整数表示,每种饲料最多只能对牛使用一次,数据保证存在解。
输入格式
第一行一个整数 v,表示需要的维他命的种类数。
第二行 v 个整数,表示牛每天需要的每种维他命的最小量。
第三行一个整数 g,表示可用来喂牛的饲料的种数。
下面 g 行,第 n 行表示编号为 n 饲料包含的各种维他命的量的多少。
输出格式
输出文件只有一行,包括牛必需的最小的饲料种数 $p$;后面有 $p$ 个数,表示所选择的饲料编号(按从小到大排列)。
如果有多个解,输出饲料序号最小的(即字典序最小)。
解题思路
1.先枚举个数len(选多少种饲料)
2.用dfs枚举在g个中选len个(next_permutation也可以)
3.如果选的饲料的v种维他命均>=牛每天需要的每种维他命的最小量,
就把这种选法对应的所有饲料编号存下来作为一种方案
4.最后把所有方案按字典序排好,取最小的输出
代码
没办法,就是喜欢(
只会)STL
#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[30];
int b[20][30];
int p[20];
int sum[30];
signed main() {
int v;
cin >> v;
for (int i = 1; i <= v; i++)
cin >> a[i];
int g;
cin >> g;
for (int i = 1; i <= g; i++) {
for (int j = 1; j <= v; j++) {
cin >> b[i][j];
}
}
vector<set<int> > ans;
set<int> tmp;
for (int len = 0; len <= g; len++) {
memset(p, 0, sizeof p);
int cnt = g;
for (int i = 0; i < len; i++) {
p[cnt] = 1;
cnt--;
}
do {
memset(sum, 0, sizeof sum);
for (int i = 1; i <= g; i++) {
if (p[i] == 1) {
for (int j = 1; j <= v; j++) {
sum[j] += b[i][j];
}
}
}
bool ok = true;
for (int i = 1; i <= v; i++) {
if (sum[i] < a[i]) {
ok = false;
break;
}
}
if (ok) {
tmp.clear();
for (int i = 1; i <= g; i++) {
if (p[i] == 1) {
tmp.insert(i);
}
}
ans.push_back(tmp);
}
} while (next_permutation(p + 1, p + g + 1));
}
sort(ans.begin(), ans.end(), [](set<int> x, set<int> y)->bool{
if (x.size() != y.size()) {
return x.size() < y.size();
}
for (auto ix = x.begin(), iy = y.begin(); ix != x.end() && iy != y.end(); ix++, iy++) {
if (*ix != *iy) {
return *ix < *iy;
}
}
return 0;
});
cout << ans.front().size() << " ";
for (auto i = ans.front().begin(); i != ans.front().end(); i++) {
cout << *i << " ";
}
return 0;
}