强迫症的吃货

晓萌作为一个营养学专家,吃东西的时候总是要考虑是否能满足他的各种营养物质需求,大家都说他是一个有强迫症的吃货。晓萌知道每种食品中营养物质的含量,请你帮他安排食谱,以保持他获得所需营养物质的同时,吃的食品的种类最少。(营养物质含量为整数,每种食品晓萌只吃一次)。

输入第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;
    }
}

猜你喜欢

转载自blog.csdn.net/WN_795/article/details/81280955