晓萌作为一个营养学专家,吃东西的时候总是要考虑是否能满足他的各种营养物质需求,大家都说他是一个有强迫症的吃货。晓萌知道每种食品中营养物质的含量,请你帮他安排食谱,以保持他获得所需营养物质的同时,吃的食品的种类最少。(营养物质含量为整数,每种食品晓萌只吃一次)。
输入第1行为一个整数V表示晓萌需要的营养物质的种类数(1≤V≤25)。
输入第2行包括用空格分隔开的V个整数,依次表示每种营养物质的需求量(1≤每个整数≤1000)。
输入第3行包括一个整数ģ表示提供可以给晓萌吃的食品的种类数(1≤G≤15)。
接下来的ģ行,每行包括用空格分隔开的V个整数,G行中的第我行中V个整数依次表示第我种食品中每种营养物质的需求量(1≤每个整数≤1000)。
输出包括空格分隔的多个数,第一个数为必需的最小的食品种数P:后面有P个数,表示所选择的食品编号(按从小到大排列);如果有多个解,输出食品序号最小的(即字典序最小)。
样例输入
4
100 200 300 400
3
50 50 50 50
200 300 200 300
900 150 389 399
样例输出
2 1 3
题解:用枚举的方式来测试每次最小的食物种数P,然后再用DFS的方式,从第一种提供的食物开始,这样DFS后的正确结果就是排好序的;
#include<iostream>
#include<cstring>
using namespace std;
int a[30],b[20][30],c[30],d[30],f[30],n,m,x,y,k,z=0,ans=0;
bool key=false;
void dfs(int t,int u)
{
if(u>=k||t>=m)//深搜结束的条件(添加的食物超过枚举或者深搜开始的地方已经超出食物种类范围)
{
return;
}
for(int i=0;i<n;i++)//(将当前位置的食物营养含量加入总和)
{
c[i]+=b[t][i];
}
d[u]=t;(记录选择的位置)
key=true;
for(int i=0;i<n;i++)//判断是否符合条件
{
if(c[i]<a[i])
{
key=false;
}
}
if(key==true&&z==0)//只有第一次符合条件的答案正确
{
z=1;
for(int i=0;i<30;i++)//用f数组来记录组合的顺序(因为d数组的记录会在之后的深搜中被打乱)
{
f[i]=d[i];
}
ans=k;
}
dfs(t+1,u+1);//加1继续
for(int i=0;i<n;i++)//不要当前食物营养,继续
{
c[i]-=b[t][i];
}
dfs(t+1,u);
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
cin>>m;
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
cin>>b[i][j];
}
}
for(int i=1;i<=m;i++)
{
memset(c,0,sizeof(c));//每次都要清空c数组,c数组是用来存放总量,避免上次影响
k=i;
dfs(0,0);
}
cout<<ans<<" ";
for(int i=0;i<ans;i++)//输出答案,最后一个数据后不能带有空格
{
if(i!=0)
{
cout<<" ";
}
cout<<f[i]+1;
}
}