• P1460 健康的荷斯坦奶牛 Healthy Holsteins(洛谷)


    题目描述

    农民 John 以拥有世界上最健康的奶牛为傲。他知道每种饲料中所包含的牛所需的最低的维他命量是多少。请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少。

    给出牛所需的最低的维他命量,输出喂给牛需要哪些种类的饲料,且所需的饲料剂量最少。

    维他命量以整数表示,每种饲料最多只能对牛使用一次,数据保证存在解。

    输入格式

    第一行一个整数 vvv,表示需要的维他命的种类数。
    第二行 vvv 个整数,表示牛每天需要的每种维他命的最小量。

    第三行一个整数 ggg,表示可用来喂牛的饲料的种数。
    下面 ggg 行,第 nnn 行表示编号为 nnn 饲料包含的各种维他命的量的多少。

    输出格式

    输出文件只有一行,包括牛必需的最小的饲料种数 ppp;后面有 ppp 个数,表示所选择的饲料编号(按从小到大排列)。

    如果有多个解,输出饲料序号最小的(即字典序最小)。

    输入输出样例

    输入 #1
    4
    100 200 300 400
    3
    50  50  50  50
    200 300 200 300
    900 150 389 399
    输出 #1
    2 1 3
    

    说明/提示

    【数据范围】
    对于 100%100\%100% 的数据,1≤v≤251le v le 251v25,1≤g≤151le g le 151g15。
    输入的所有整数在 [1,1000][1,1000][1,1000] 范围内。

    代码与题解:

    #include<iostream>
    #include<algorithm>
    #include<string.h>
    #include<queue>
    using namespace std;
    
    
    //解题核心思想:题目的最终目的是求最少的饲料种类数(与维他命剂量没关系),因此可以使用bfs算法进行求解
    //本题实际上dfs方式求解更简单(只需要dfs(选当前某一饲料)和dfs(不选当前某一饲料即可))
    //但关键点在于:最有解中种类数相同的有好几种情况满足,题目要求输出最小的编号
    
    //思路解法一:每次bfs一个节点 直到找到满足的条件为止  记录饲料种数和饲料编号  因此可以使用for循环(但是可能会出现MLE)
    //思路解法二:把所有的饲料(每一种)当做出发结点,首先全部压入队列(编号小的先压入),一起进行bfs,因此只要第一次找到满足条件的则是满足条件且编号最小的解
    int m,n;
    int mini[26];       //mini[i]代表牛对第i种维他命的最小需求
    int si[30][30];     //si[i][j]代表第i种饲料中j维他命的含量
    int color[30]={0};        //用于标记哪种饲料被使用过
    
    typedef struct node{
        int v[30];      //储存结点的维他命数量的情况
        int dis[16];    //储存选择的饲料种类(路径)
        int num;          //选择饲料的种类数量
    }N;
    
    bool panduan(int *a){     //判断是否满足了最小要求
        for(int i=1;i<=m;i++){
            if(a[i]<mini[i])    return false;       //只要有一种维他命缺少就不满足
        }
        return true;
    }
    
    void bfs(){
        queue<N> q;
        for(int i=1;i<=n;i++){          //n种饲料  因此先生成n个初始结点
            N temp;
            for(int j=1;j<=m;j++){      //m种维他
                temp.v[j]=si[i][j];
            }
            temp.dis[0]=i;      //注意路径下标从0开始 从0~temp.num-1
            temp.num=1;
            q.push(temp);
        }
    
        while(!q.empty()){
            N cur=q.front();
            q.pop();
    
            if(panduan(cur.v)){         //找到了立即输出
                cout<<cur.num<<" ";
                for(int i=0;i<cur.num;i++){
                    cout<<cur.dis[i]<<" ";
                }
                return;
            }
    
            //若上述没有找到 则执行下面的遍历其他节点
            //节点压入队列的顺序方式为  只压入比刚刚pop出的节点编号大的结点(而且压入的顺序是从小到大  即最开始从pop的结点编号+1开始)
            //每个初始结点都按照这种只入队编号比pop结点编号大的结点的方式,并且节点最开始也是从1~n的,因此不需要担心会有遗漏的情况出现
            //可以理解为:遍历的方向或者入队顺序:
            //第一个初始点出发(指的是饲料编号):1 2 3 ……n
            //第二个初始点出发: 2 3 4…… n 以此类推
    
            for(int i=cur.dis[cur.num-1]+1;i<=n;i++){       //这样设置可以保证i一定未走过
                N next=cur;
                for(int j=1;j<=m;j++){          //吃了第i种饲料 所以把对应的维生素加上
                    next.v[j]+=si[i][j];
                }
                next.dis[next.num]=i;
                next.num++;
                q.push(next);
            }
        }
    }
    
    
    int main(){
        cin>>m;
        for(int i=1;i<=m;i++){
            cin>>mini[i];
        }
    
        cin>>n;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cin>>si[i][j];
            }
        }
        bfs();
        return 0;
    }
  • 相关阅读:
    虫洞wormhole
    号码锁 Combination Lock
    滑雪课程设计Ski Course Design
    修理牛棚 Barn Repair
    JMeter录制脚本
    JMeter简单性能测试(适合初学者)
    JMeter Building a Database Test Plan
    JMeter脚本参数化和断言设置( CSV Data Set Config )
    JMeter分布式性能测试
    JMeter 参数化、检查点、集合点
  • 原文地址:https://www.cnblogs.com/xwh-blogs/p/13719427.html
Copyright © 2020-2023  润新知