原题链接:
思路:仔细看题会发现G(饲料种数在1~15之间),每种饲料有两种情况,取或者不取,则总共有2^15=32768种可能,并不多可以采取枚举这32768种可能的做法解题。注意找到一种选择之后,不必判断每一种维他命是否得到满足,比如这种选择不能使第一种维他命得到满足,则舍弃这种选择,后面的几种维他命就不必再进行 判断了,这是一种高效的做法,否则很可能超时的。还有找到一种选择后,不能break掉,因为题目要求输出使用饲料最少的选择,而且题目中2和3也满足各种 维他命量,但是却选择的1和3,说明序号小的优先选择。所以在遍历了所有的选择后要找出需要饲料的种数最少的,当需要的饲料种数相同时,要找出需要的饲料序号靠前的。
源代码:
/*
ID: supersnow0622
PROG: holstein
LANG: C++
*/
#include <iostream>
#include <fstream>
#include <string>
#include<memory.h>
using namespace std;
int kinds[26];
int feed[16][26];
int sum[26];
char str[17];
int V,G;
void convert(int n)
{
string temp;
while(n!=0)
{
temp+=n%2+'0';
n/=2;
}
int i,j;
for(i=1;i<=G-temp.length();i++)
str[i]='0';
for(j=temp.length()-1;j>=0;j--,i++)
str[i]=temp[j];
str[i]='\0';
}
int main() {
ofstream fout ("holstein.out");
ifstream fin ("holstein.in");
string s,Min="1111111111111111";
int Mincount;
fin>>V;
for(int i=1;i<=V;i++)
fin>>kinds[i];
fin>>G;
for(int i=1;i<=G;i++)
for(int j=1;j<=V;j++)
fin>>feed[i][j];
int MAX=1<<G,count;
bool judge;
for(int i=1;i<MAX;i++)
{
memset(str,'0',sizeof(str));
memset(sum,0,sizeof(sum));
convert(i);
judge=true;
for(int k=1;k<=V;k++)
{
for(int j=1;j<=G;j++)
if(str[j]=='1')
{
sum[k]+=feed[j][k];
}
if(sum[k]<kinds[k])
{
judge=false;
break;
}
}
if(judge)
{
count=0;s="";
for(int i=1;i<=G;i++)
if(str[i]=='1')
{
count++;
s+=i+'0';
}
if(Min.length()>s.length()||(Min.length()==s.length()&&Min>s))
{
Min=s;Mincount=count;
}
}
}
fout<<Mincount;
for(int i=0;i<Mincount;i++)
fout<<" "<<(int)(Min[i]-'0');
return 0;
}