P1460 [USACO2.1] 健康的荷斯坦奶牛 Healthy Holsteins

洛谷:P1460 [USACO2.1]健康的荷斯坦奶牛 Healthy Holsteins(DFS) 题目描述 农民 John 以拥有世界上最健康的奶牛为傲。他知道每种饲料中所包含的牛所需的最低的维他命量是多少。请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少。 给出牛所需的最低的维他命量,输出喂给牛需要哪些种类的饲料,且所需的饲料剂量最少。 维他命量以整数表示,每种饲料最多只能对牛使用一次,数据保证存在解。 输入格式 第一行一个整数 vv,表示需要的维他命的种类数。 第二行 vv 个整数,表示牛每天需要的每种维他命的最小量。 第三行一个整数 gg,表示可用来喂牛的饲料的种数。 下面 gg 阅读详情

记录139

#include<bits/stdc++.h> 
using namespace std; 
const int N=30; 
int v; // 定义全局变量v,表示需要的维他命种类数
int need[N]; // 记录每种维他命每天需要的最小量
int g; // 定义全局变量g,表示饲料的种数
int feed[N][N]; // 二维数组,feed[i][j]表示第i种饲料含有的第j种维他命量
int path[N]; // 记录当前搜索路径中选择的饲料编号
bool found=false; // 标记是否已经找到了最优解

// 检查当前路径中选择的饲料是否满足所有维他命的需求
bool check(int cnt){
    int sum[N]={}; // 临时数组,记录当前组合下每种维他命的总量
    for(int i=1;i<=cnt;i++){ // 遍历当前选中的每一种饲料
        int id=path[i]; // 获取该饲料的编号
        for(int j=1;j<=v;j++){ // 累加该饲料提供的各种维他命
            sum[j]+=feed[id][j];
        }
    }
    for(int i=1;i<=v;i++){ // 检查每种维他命是否达标
        if(sum[i]<need[i]){ // 如果有任何一种维他命不足
            return false; // 返回不合法
        }
    }
    return true; // 所有维他命均满足需求
}

// 深度优先搜索(DFS)函数,cur表示当前正在选第几个,cnt表示总共需要选几个
void dfs(int cur,int cnt){
    if(found) return;// 如果已经找到了最优解(因为我们是按数量从小到大搜的,找到即最优)
       // 直接剪枝返回
    if(cur>cnt){ // 如果已经选够了cnt种饲料,越界收网 
        if(check(cnt)){ // 检查当前方案是否满足维他命需求
            cout<<cnt; // 输出最少的饲料种数
            for(int i=1;i<=cnt;i++) cout<<" "<<path[i]; // 按顺序输出选择的饲料编号          
            found=true; // 标记已找到,后续搜索全部剪枝
        }
        return; // 结束当前递归分支
    }
    // 从上一个选择的饲料编号+1开始枚举,保证选择的饲料编号是递增的(字典序最小)
    // 剪枝:剩下的饲料数量必须足够凑齐cnt种
    for(int i=path[cur-1]+1;i<=g-(cnt-cur+1)+1;i++){
        path[cur]=i; // 选择第i种饲料
        dfs(cur+1,cnt); // 继续选择下一种
    }
}

int main(){ // 主函数入口
    ios::sync_with_stdio(false); // 关闭标准流同步,提升输入输出效率
    cin.tie(0); // 解除cin与cout的绑定,加快读取速度
    
    cin>>v; // 读入维他命种类数v
    for(int i=1;i<=v;i++) cin>>need[i]; // 读入每种维他命的需求量
    cin>>g; // 读入饲料种数g
    for(int i=1;i<=g;i++){ // 读入每种饲料的维他命含量
        for(int j=1;j<=v;j++) cin>>feed[i][j];   
    }  
    // 从小到大枚举需要选择的饲料种数(1种,2种,3种...)
    for(int i=1;i<=g;i++){
        path[0]=0; // 初始化路径起点为0(保证第一个饲料从1开始选)
        dfs(1,i); // 尝试选i种饲料
        if(found) break;// 如果找到了,直接跳出循环        
    }
    return 0; // 程序正常结束
}

题目传送门https://www.luogu.com.cn/problem/P1460


前言

我是一名专注信奥赛(CSP-J/S、NOIP)的教练。

  • 如果你觉得这篇题解对你有帮助,欢迎点击关注我的优快云账号,我会持续更新高质量算法解析。
  • 我深知算法思维的构建远比单纯通过题目更重要,本系列题解不局限于AC代码的堆砌,而是致力于拆解题目背后的逻辑链条与核心知识点
  • 备赛路上若遇瓶颈,欢迎随时评论或私信,我将甄选典型疑难问题,通过视频讲解或撰写专项文章的形式,为你提供深度答疑。

核心解题思路

这道题是一道经典的迭代加深搜索(Iterative Deepening Search, IDS)问题。

  1. 问题转化与策略选择:
    题目要求我们选出最少的饲料种数,并且在种数相同的情况下,输出字典序最小的饲料编号组合。由于饲料种数 g≤15g≤15 ,数据规模较小,我们可以直接枚举。但如果我们直接暴力搜索所有子集,很难保证找到的第一个解就是“种数最少”的。因此,我们采用迭代加深的策略:从选 1 种饲料开始尝试,如果找不到可行解,再尝试选 2 种,依此类推。这样,我们找到的第一个可行解,必然就是饲料种数最少的最优解。

  2. 保证字典序最小:
    在 DFS 搜索过程中,我们强制让选择的饲料编号严格递增(即下一个选择的饲料编号必须大于上一个)。这样,当我们从小到大枚举饲料时,自然保证了最终输出的组合是字典序最小的。

  3. 全局剪枝:
    因为我们是按照饲料种数从少到多进行搜索的,一旦在某一层(比如选 k 种)找到了一个可行解,那么它一定是最优的。此时我们可以设置一个全局标志位 found,直接终止所有后续的搜索,极大提升效率。


代码分块详细解释

1. 头文件、常量与全局变量定义

#include<bits/stdc++.h> 
using namespace std; 
const int N=30; 
int v; // 定义全局变量 v,表示需要的维他命种类数
int need[N]; // 记录每种维他命每天需要的最小量
int g; // 定义全局变量 g,表示饲料的种数
int feed[N][N]; // 二维数组,feed[i][j] 表示第 i 种饲料含有的第 j 种维他命量
int path[N]; // 记录当前搜索路径中选择的饲料编号
bool found=false; // 标记是否已经找到了最优解
  • 详细分析:path 数组是本题记录答案的关键,它用来存储当前 DFS 路径上选中的饲料编号。found 是一个全局剪枝变量,配合迭代加深的策略,一旦找到答案就彻底停止搜索。

2. 合法性检查函数(check)

// 检查当前路径中选择的饲料是否满足所有维他命的需求
bool check(int cnt){
    int sum[N]={}; // 临时数组,记录当前组合下每种维他命的总量
    for(int i=1;i<=cnt;i++){ // 遍历当前选中的每一种饲料
        int id=path[i]; // 获取该饲料的编号
        for(int j=1;j<=v;j++){ // 累加该饲料提供的各种维他命
            sum[j]+=feed[id][j];
        }
    }
    for(int i=1;i<=v;i++){ // 检查每种维他命是否达标
        if(sum[i]<need[i]){ // 如果有任何一种维他命不足
            return false; // 返回不合法
        }
    }
    return true; // 所有维他命均满足需求
}
  • 详细分析:当 DFS 选够了指定数量(cnt)的饲料后,调用此函数进行验证。它遍历 path 数组中选中的饲料,将它们对应的维他命含量累加到 sum 数组中,最后逐一与 need 数组中的最低需求量进行比较。只要有一种维他命不达标,当前组合即为无效。

3. 核心逻辑:DFS 与字典序保证

// 深度优先搜索(DFS)函数,cur 表示当前正在选第几个,cnt 表示总共需要选几个
void dfs(int cur, int cnt){
    if(found) return; // 如果已经找到了最优解,直接剪枝返回
    if(cur > cnt){ // 如果已经选够了 cnt 种饲料,越界收网 
        if(check(cnt)){ // 检查当前方案是否满足维他命需求
            cout << cnt; // 输出最少的饲料种数
            for(int i=1;i<=cnt;i++) cout << " " << path[i]; // 按顺序输出选择的饲料编号          
            found = true; // 标记已找到,后续搜索全部剪枝
        }
        return; // 结束当前递归分支
    }
    // 从上一个选择的饲料编号+1开始枚举,保证选择的饲料编号是递增的(字典序最小)
    // 剪枝:剩下的饲料数量必须足够凑齐 cnt 种
    for(int i = path[cur-1] + 1; i <= g - (cnt - cur + 1) + 1; i++){
        path[cur] = i; // 选择第 i 种饲料
        dfs(cur+1, cnt); // 继续选择下一种
    }
}
  • 详细分析:这是代码的灵魂。
    • 字典序保证:for 循环的起始条件 i = path[cur-1] + 1 是核心。它强制要求下一个选择的饲料编号必须大于上一个,从而保证了选出的组合是严格递增的,自然满足字典序最小的要求。
    • 可行性剪枝:循环的终止条件 i <= g - (cnt - cur + 1) + 1 是一个经典的组合数学剪枝。它的意思是:当前还剩 cnt - cur + 1 个位置需要填充,如果从当前位置 i 往后数,剩下的饲料总数不够填满这些位置,那么继续枚举 i 及其后面的数就没有意义了,直接跳出循环。
    • 全局最优剪枝:一旦 check 通过,输出答案并将 found 置为 true,所有的递归层都会因为开头的 if(found) return 而迅速退出。

4. 主函数:迭代加深框架

int main(){ 
    ios::sync_with_stdio(false); 
    cin.tie(0); 
    
    cin >> v; // 读入维他命种类数 v
    for(int i=1;i<=v;i++) cin >> need[i]; // 读入每种维他命的需求量
    cin >> g; // 读入饲料种数 g
    for(int i=1;i<=g;i++){ // 读入每种饲料的维他命含量
        for(int j=1;j<=v;j++) cin >> feed[i][j];   
    }  
    
    // 从小到大枚举需要选择的饲料种数(1种,2种,3种...)
    for(int i=1;i<=g;i++){
        path[0]=0; // 初始化路径起点为 0(保证第一个饲料从 1 开始选)
        dfs(1, i); // 尝试选 i 种饲料
        if(found) break; // 如果找到了,直接跳出循环        
    }
    return 0; 
}
  • 详细分析:主函数完美实现了迭代加深的框架。外层 for 循环从 1 到 gg 依次枚举需要选择的饲料数量。path[0]=0 的初始化是为了配合 DFS 中的 path[cur-1] + 1,确保第一种饲料可以从编号 1 开始合法选择。一旦 found 变为真,立刻 break,保证了答案的绝对最优性。

核心逻辑总结表

代码模块核心变量/操作精炼作用解决的痛点
迭代加深框架主函数中的 for(int i=1;i<=g;i++)从小到大枚举选择的饲料种数保证了找到的第一个解必然是饲料种数最少的最优解
字典序保证i = path[cur-1] + 1强制下一个选择的编号大于上一个避免了重复组合,并天然保证了输出结果的字典序最小
可行性剪枝i <= g - (cnt - cur + 1) + 1限制枚举的上界当剩余饲料不足以凑齐目标数量时提前终止,大幅减少无效搜索
全局最优剪枝if(found) return找到答案后立即停止所有递归避免了在找到最优解后继续浪费时间去搜索更差或同级的解
合法性验证check(cnt) 函数累加维他命并比对最低需求在搜索树的叶子节点准确判定当前饲料组合是否有效
路径记录path[N] 数组记录 DFS 过程中选中的饲料编号将搜索状态与最终答案的输出完美解耦
题解:洛谷 [P1460 [USACO2.1] 健康的荷斯坦奶牛 Healthy Holsteins 题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。他知道每种饲料中所包含的牛所需的最低的维他命量是多少。请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少。要求选择最少数量的饲料,使得每种维他命的总量均满足最小需求。给出牛所需的最低的维他命量,输出喂给牛需要哪些种类的饲料,且所需的饲料剂量最少。个整数,表示牛每天需要的每种维他命的最小量。,表示需要的维他命的种类数。,表示可用来喂牛的饲料的种数。饲料包含的各种维他命的量的多少。 阅读详情

相关推荐

ESP32驱动GC9A01圆形屏实战:Arduino平台LVGL移植与图像显示优化

本文详细介绍了在Arduino平台上使用ESP32驱动GC9A01圆形屏的实战指南,包括硬件连接、LVGL移植与图像显示优化。通过SPI配置、LVGL库安装和双缓冲机制等技巧,帮助开发者快速实现高效显示效果,适用于智能家居控制面板等应用场景。

weixin_29182481的博客 736

洛谷P1460 [USACO2.1] 健康的荷斯坦奶牛 Healthy Holsteins

农民 John 以拥有世界上最健康的奶牛为傲。他知道每种饲料中所包含的牛所需的最低的维他命量是多少。请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少。给出牛所需的最低的维他命量,输出喂给牛需要哪些种类的饲料,且所需的饲料剂量最少。维他命量以整数表示,每种饲料最多只能对牛使用一次,数据保证存在解。

fearlessness6的博客 625

【Linux 驱动开发】STM32MP1 LCD 显示系统完整实践指南

STM32MP1 LCD显示系统实践指南 本文全面介绍STM32MP1平台实现MIPI DSI LCD显示的完整流程,涵盖硬件连接、设备树配置、显示原理和驱动实现。主要内容包括: 硬件连接:详细说明MIPI DSI差分对、背光PWM、复位/供电管脚的连接方式 设备树配置: PWM背光控制节点设置 LTDC与DSI端口映射关系 Panel节点参数定义 显示基础:讲解LCD/OLED显示原理、常见接口类型(RGB/LVDS/MIPI/HDMI)及信号时序 驱动实现。

猫猫的小茶馆 496

编程刷题-P1460 [USACO2.1] 健康的荷斯坦奶牛 Healthy Holsteins DFS/回溯

已选 {1,2} 再选 3 号 → 已选{1,2,3}总量:满足!此时 s = 3,minn 更新为 3,答案数组 ans = {1,2,3}。但搜索还没完,DFS 会继续尝试其它可能更优的解。继续搜索路径 B 中“选 2 号”那条路:已选{2},再选 3 号 → {2,3}总量:满足!此时 s=2 < 3,于是 minn 更新为 2,答案数组 ans = {2,3}(由于按编号顺序选,天然就是升序)。

Fuxiao___的博客 609

DCA决策曲线的解读和代码实现

0.决策曲线 决策曲线分析法(Decision Curve Analysis,DCA)是个与ROC曲线相提并论的相对比较新的模型评价方法。 关于它的原理,长篇大论的医学统计学知识解读实在不是我的强项,放上两个链接偷偷懒: https://www.plob.org/article/12455.html https://www.iikx.com/news/statistics/1622.html 如果想看文章,这篇里的fig7就是:https://www.ncbi.nlm.nih.gov/pmc/artic

weixin_42960896的博客 1万+

C和C++Everything教程的简介

C和C++Everything教程的简介 C和C++Everything教程,该专栏目前已有8000博文,订阅该专栏相当于同时订阅以下所有收费专栏

希望我的博客,能帮上你解决学习中工作中所遇到的问题 4392

P1460 [USACO2.1] 健康的荷斯坦奶牛 Healthy Holsteins题解

农民 John 以拥有世界上最健康的奶牛为傲。他知道每种饲料中所包含的牛所需的最低的维他命量是多少。请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少。给出牛所需的最低的维他命量,输出喂给牛需要哪些种类的饲料,且所需的饲料剂量最少。维他命量以整数表示,每种饲料最多只能对牛使用一次,数据保证存在解。

2302_79336517的博客 817

YOLOv11在视频流中的时序建模改进-(加入ConvLSTM或Transformer捕捉帧间关联)

本文提出了一种结合ConvLSTM和Transformer的改进YOLOv11算法,用于增强视频目标检测的时序建模能力。针对视频检测中运动模糊、遮挡等挑战,研究分析了ConvLSTM的局部时空特征建模和Transformer的全局注意力机制之间的互补性。通过数学公式详细阐述了ConvLSTM的门控机制和Transformer的自注意力计算原理,并提出分层融合策略:底层使用ConvLSTM处理高分辨率特征捕捉局部运动,高层应用Transformer建立全局时空关联。改进方案在YOLOv11架构中插入时序增强模

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 680

P1460 [USACO2.1]健康的荷斯坦奶牛 Healthy Holsteins

题目描述 农民 John 以拥有世界上最健康的奶牛为傲。他知道每种饲料中所包含的牛所需的最低的维他命量是多少。请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少。 给出牛所需的最低的维他命量,输出喂给牛需要哪些种类的饲料,且所需的饲料剂量最少。 维他命量以整数表示,每种饲料最多只能对牛使用一次,数据保证存在解。 输入格式 第一行一个整数 vv,表示需要的维他命的种类数。 第二行 vv 个整数,表示牛每天需要的每种维他命的最小量。 第三行一个整数 gg,表示可用来喂牛的饲料的种数。 下面 gg

Alex_Mercers的博客 703

杰理 JL701N/JL703N USB MIDI 使用教程

摘要:本教程介绍如何在杰理JL701N/JL703N音箱的可视化SDK中配置USB MIDI功能。主要步骤包括:1)启用PC模式;2)修改SDK宏定义启用USB MIDI;3)实现MIDI数据接收处理逻辑;4)调用接口发送MIDI数据;5)使用MIDI-OX测试功能。针对低版本SDK可能出现的设备识别问题,提供了在midi.c文件中添加特定代码行的解决方案。使用前需确保SDK版本达标,并注意备份原始文件。

qq_42014563的博客 1268

滤波算法实现大全——基于匀速直线运动模型的kalman滤波算法

滤波算法实现大全——基于匀速直线运动模型的kalman滤波算法

jane0819的博客 523

P1460 [USACO2.1] 健康的荷斯坦奶牛 Healthy Holsteins题解复盘

【代码】P1460 [USACO2.1] 健康的荷斯坦奶牛 Healthy Holsteins题解复盘。

2604_96548757的博客 169

概率的接力:拆解大模型“预测下一个词“的底层逻辑

大模型的智能不在于它拥有了意识,而在于它用纯数学的架构,将人类语言的复杂结构压缩为可计算的向量轨迹与概率接力。当我们不再将其拟人化为"思考者",而是视作高维条件概率引擎时,才能真正驾驭它。预测下一个词,从来不是终点,而是起点。未来的核心竞争力,属于那些能洞察其统计本质、善用其模式生成能力,并以人类理性与事实为锚点的协作者。词元的轨迹终会止步于上下文窗口,但对技术底层的清醒认知,才是跨越幻觉、走向真实智能的基石。

AI浩 332

洛谷P1460 [USACO2.1]健康的荷斯坦奶牛 Healthy Holsteins

传送门:https://www.luogu.com.cn/problem/P1460 写这道题题解是因为对于我对题目的理解是对的,思路也比较清晰。但是在DFS代码的技巧上有欠缺导致无法写出完全AC的代码。从题解中我对DFS函数定义的参数列表有了进一步的了解,在DFS算法中,对与参数列表的定义也是极为重要的,有技巧性地定义参数列表可以减小代码的复杂度,也让写题思路更加清晰。 同时,对与DFS的标记访问和去除标记也清晰了一些,比第一天刚开始摸索时不知道从何下手进步了不少,继续加油! 言归正传。这道题目还是

Study_Study_X的博客 944

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

P1460 [USACO2.1]健康的荷斯坦奶牛 Healthy Holsteins [洛谷]

P1460 [USACO2.1]健康的荷斯坦奶牛 Healthy Holsteins

German_Sparrow的博客 544

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

洛谷 P1460 [USACO2.1] 健康的荷斯坦奶牛 Healthy Holsteins

他知道每种饲料中所包含的牛所需的最低的维他命量是多少。请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少。给出牛所需的最低的维他命量,输出喂给牛需要哪些种类的饲料,且所需的饲料剂量最少。下面 g 行,第 n 行表示编号为 n 饲料包含的各种维他命的量的多少。第二行 v 个整数,表示牛每天需要的每种维他命的最小量。对于 100% 的数据,1≤v≤25,1≤g≤15。第三行一个整数 g,表示可用来喂牛的饲料的种数。第一行一个整数 v,表示需要的维他命的种类数。

2401_87918203的博客 196

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

洛谷----P1460 [USACO2.1]健康的荷斯坦奶牛 Healthy Holsteins

题目描述 农民 John 以拥有世界上最健康的奶牛为傲。他知道每种饲料中所包含的牛所需的最低的维他命量是多少。请你帮助农夫喂养他的牛,以保持它们的健康,使喂给牛的饲料的种数最少。 给出牛所需的最低的维他命量,输出喂给牛需要哪些种类的饲料,且所需的饲料剂量最少。 维他命量以整数表示,每种饲料最多只能对牛使用一次,数据保证存在解。 输入格式 第一行一个整数v,表示需要的维他命的种类数。 第二行v个整数,表示牛每天需要的每种维他命的最小量。 第三行一个整数g,表示可用来喂牛的饲料的种数。 下面...

今天会营业的博客 356

洛谷 个人题解 P1460 [USACO2.1] 健康的荷斯坦奶牛 Healthy Holsteins

【代码】洛谷 个人题解 P1460 [USACO2.1] 健康的荷斯坦奶牛 Healthy Holsteins。

HZYSX的博客 356

P1460 [USACO2.1]健康的荷斯坦奶牛 Healthy Holsteins (搜索 广度优先搜索,BFS深度优先搜索,DFS)

P1460 [USACO2.1]健康的荷斯坦奶牛 Healthy Holsteins (搜索 广度优先搜索,BFS深度优先搜索,DFS)

goblin的博客 585

[USACO2.1] Healthy Holsteins (健康的荷斯坦奶牛) 题解

这是一道深搜(枚举子集)的板子题,刚学的时候还是很值得做的。

R_D_LEGEND的博客 1412
上一篇: P9011 [USACO23JAN] Air Cownditioning II B
下一篇: P1036 [NOIP 2002 普及组] 选数
谢天谢地AC了 | 信奥教练
博客等级 码龄1年 53粉丝 177原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值