USACO-Section2.1 Healthy Holsteins [搜索][枚举]
2017-07-16 16:31
447 查看
题目大意
农民JOHN以拥有世界上最健康的奶牛为傲。他知道每种饲料中所包含的牛所需的最低的维他命量是多少。请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少。给出牛所需的最低的维他命量,输出喂给牛需要哪些种类的饲料,且所需的饲料剂量最少。
维他命量以整数表示,每种饲料最多只能对牛使用一次,数据保证存在解。
格式
PROGRAM NAME: holsteinINPUT FORMAT:
(file holstein.in)
第1行:一个整数V(1<=V<=25),表示需要的维他命的种类数。
第2行:V个整数(1<=每个数<=1000),表示牛每天需要的每种维他命的最小量。
第3行:一个整数G(1<=G<=15),表示可用来喂牛的饲料的种数。
下面G行,第n行表示编号为n饲料包含的各种维他命的量的多少。
OUTPUT FORMAT:
(file holstein.out)
输出文件只有一行,包括
牛必需的最小的饲料种数P
后面有P个数,表示所选择的饲料编号(按从小到大排列)。
如果有多个解,输出饲料序号最小的(即字典序最小)。
SAMPLE INPUT
4
100 200 300 400
3
50 50 50 50
200 300 200 300
900 150 389 399
SAMPLE OUTPUT
2 1 3
(copy from nocow)
题解:
这题每种物品都只有选和不选两种可能,G种物品就只有 2G−1 种选择。觉得和背包问题有些像,但是开不了那么大的数组。想用线性规划,但也太复杂了。。所以还是枚举吧,数据又不大。
这题可以用深搜来做,每种物品选或者不选都考虑一下。更好的方法是用位运算来枚举所有的可能。非递归的方法总是比递归的方法要安全一些。
G位的二进制数,每一位都表示一种饲料是否选择。有 2G−1 种选择, 只要把1~2G−1 这些数字都枚举一遍,对每个数字用位运算“&”来查看每一个二进制位是否为1就能确定某个物品是否选择。枚举所有可能的情况,然后就可以找到最优解了。
代码
#include <iostream> #include <fstream> #include <cstring> #define MAXV 30 #define MAXG 20 #define cin fin #define cout fout using namespace std; ifstream fin("holstein.in"); ofstream fout("holstein.out"); int V, G; int require[MAXV]; int feed[MAXG][MAXV]; int cnt, ans[MAXG]; void solve() { cnt = G; for (int i = 0; i < G; i++) ans[i] = i; int endi = 1 << G; //G位的二进制数,每一位都表示一种饲料是否选择。有2^G-1种选择 for (int i = 0; i < endi; i++) { int t = 0, k = 1; int selected[MAXG]; int vita[MAXV]; memset(selected, 0, sizeof(selected)); memset(vita, 0, sizeof(vita)); for (int j = 0; j < G; j++) { if (i & k) selected[t++] = j; //用位运算“&”来查看每一个二进制位是否为1 k <<= 1; } for (int j = 0; j < t; j++) { for (int l = 0; l < V; l++) vita[l] += feed[selected[j]][l]; } //当前选择是否满足条件 bool flag = true; for (int j = 0; j < V; j++) { if (vita[j] < require[j]) { flag = false; break; } } if (!flag) continue;//不满足 if (t < cnt) {//满足,且用的饲料种数更少 cnt = t; for (int j = 0; j < t; j++) { ans[j] = selected[j]; } } } } int main() { cin >> V; for (int i = 0; i < V; i++) cin >> require[i]; cin >> G; for (int i = 0; i < G; i++) for (int j = 0; j < V; j++) cin >> feed[i][j]; solve(); cout << cnt << " "; for (int i = 0; i < cnt-1; i++) cout << ans[i]+1 << " "; cout << ans[cnt-1]+1 << endl; return 0; }
扩展
关于位运算,C++有一个bitset,使用起来非常方便。这题也可以用bitset来做。在下面的代码中说明bitset的基本用法:
//#include<iostream> #include<fstream> #include<bitset> //头文件 #define N 26 #define M 16 using namespace std; ifstream cin("holstein.in"); ofstream cout("holstein.out"); int n, m, ans=16; bitset<M> minbit(0); //声明bitset变量时,必须指定一个常数M表示二进制数的位数 //minbit(0) 表示声明了一个变量 minbit, 它的10进制值为0 //二进制的表示也就是M个0 int V , G[M] ; int main() { cin >> n; for(int i=0; i<n; i++) cin >> V[i]; cin >> m; for(int i=0; i<m; i++) for(int j=0; j<n; j++) cin >> G[i][j]; int T = (1<<m); for(int i=1; i<T; i++) { int c = {0}; bitset<M> bit(i); for(int j=0; j<m; j++) if(bit[j]) //枚举二进制数的每一位是1或0 for(int l=0; l<n; l++) c[l] += G[j][l]; bool ok = true; for(int j=0; j<n; j++) if(c[j] < V[j]) { ok = false; break; } if(ok && bit.count() < ans) //方法count()输出二进制数中1的个数 { ans = bit.count(); minbit = bit; } } cout << minbit.count(); for(int i=0; i<M; i++) if(minbit[i]) cout << " " << i+1; cout << endl; return 0; }
除此之外,bitset还直接支持 & | ^等操作,其他一些方法:set()可以将二进制位置1,reset()可以置0,flip()可以翻转二进制位。一次记不住,多用几次就记住了。
相关文章推荐
- USACO-Section2.1 Healthy Holsteins【宽度优先搜索/深度优先搜索】
- USACO-Section2.1 Hamming Codes [搜索]
- USACO section 2.1 Healthy Holsteins(枚举,二进制存储)
- USACO Section 2.1 Ordered Fractions(枚举)
- USACO section 2.1 Healthy Holsteins(枚举,二进制存储)
- USACO-Section2.1 The Castle [搜索][深度优先搜索]
- USACO-Section1.3 Wormholes 【深度优先搜索】【暴力枚举】
- USACO Section 2.1 Ordered Fractions - 用GCD判合法的简单搜索
- USACO-Section2.1 Hamming Codes【暴力枚举】
- USACO Section2.1 Sorting a Three-Valued Sequence 解题报告
- USACO-Section2.1 sort3[排序][递归]
- USACO Section 4.3 Letter Game - 简单枚举
- USACO Section 2.1: Healthy Holsteins
- USACO-Section1.6 Superprime Rib (枚举)
- USACO-Section1.4 Arithmetic Progressions[其他][暴力枚举]
- USACO-Section1.3 Prime Cryptarithm【暴力枚举】
- USACO section 2.1 Ordered Fractions(简单数学求约数加个排序)
- POJ1164 + USACO Section 2.1 The Castle - 简单的DFS...
- USACO-Section 1.3 Prime Cryptarithm(枚举)
- USACO Section 2.1 The Castle