【递归完全搜索】USACO Bronze 2023 January - 牛栏降温 IIAir Cownditioning II
题目描述
由于今年夏天农场经历了有记录以来最热的夏天,农夫 John 需要给奶牛降温。于是他决定投资一些空调设备。
农夫 John 有 NNN 头奶牛(1≤N≤201 \le N \le 201≤N≤20),它们生活在一排连续的牛栏里,牛栏编号为 111 到 100100100。第 iii 头奶牛占据从牛栏 sis_isi 到牛栏 tit_iti 的区间。不同奶牛占据的区间是不重叠的。
不同奶牛对降温的需求不同,第 iii 头奶牛必须被降温至少 cic_ici 单位,也就是说,第 iii 头奶牛占据的每个牛栏的温度都必须至少降低 cic_ici 单位。
农场有 MMM 台空调,编号为 111 到 MMM(1≤M≤101 \le M \le 101≤M≤10)。第 iii 台空调的运行成本是 mim_imi(1≤mi≤10001 \le m_i \le 10001≤mi≤1000),它可以降温从牛栏 aia_iai 到牛栏 bib_ibi 的区间。第 iii 台空调能将它覆盖区间内的所有牛栏温度降低 pip_ipi 单位(1≤pi≤1061 \le p_i \le 10^61≤pi≤106)。空调覆盖的区间可以相互重叠。
农场的运营成本很高,所以农夫 John 有预算限制。请你计算出使所有奶牛降温要求都得到满足的情况下,最小需要花费多少钱。
保证:如果开启所有空调,所有奶牛的需求一定能够满足。
输入格式
第一行:两个整数 NNN 和 MMM。
接下来 NNN 行:每行三个整数 si,ti,cis_i, t_i, c_isi,ti,ci,表示第 iii 头奶牛占据的牛栏区间和降温需求。
接下来 MMM 行:每行四个整数 ai,bi,pi,mia_i, b_i, p_i, m_iai,bi,pi,mi,表示第 iii 台空调的覆盖区间、降温能力和运行成本。
输出格式
输出一个整数,表示满足所有奶牛降温需求的最低花费。
样例输入
2 4
1 5 2
7 9 3
2 9 2 3
1 6 2 8
1 2 4 2
6 9 1 5
样例输出
10
样例说明
一种花费最少的方案是选择降温区间为 [2,9][2,9][2,9]、[1,2][1,2][1,2] 和 [6,9][6,9][6,9] 的空调,它们的成本分别是 333、222、555,总共 101010,满足了所有奶牛的降温要求。
提交链接
Air Cownditioning II
思路分析
🔍 核心思想:完全搜索 + 模拟验证
由于空调数量 M≤10M \le 10M≤10,所以空调的组合总数最多为 2M=10242^M = 10242M=1024,可以枚举所有可能的开关状态进行暴力搜索。
✅ 步骤总结如下
-
步骤 111:枚举空调组合
使用 位运算/二进制掩码(bitmask) 来表示空调的使用状态。共 2M2^M2M 种空调使用方案,逐一遍历。
-
步骤 222:模拟该组合的降温效果
使用一个数组
range[1..100]
表示每个牛栏的总降温量。对于每一台开启的空调,将其降温效果 pip_ipi 累加到其作用区间 [ai,bi][a_i, b_i][ai,bi] 内的每个牛栏上。 -
步骤 3:检查是否满足所有奶牛需求
遍历所有奶牛,对于每头奶牛占据的区间 [si,ti][s_i, t_i][si,ti]:检查其区间内每一个牛栏是否降温达到了 cic_ici。如果有任一位置不满足,则当前方案不合法,跳过。
-
步骤 444:更新最小成本
如果当前组合合法,则记录其成本,更新全局最小值
min_cost
。
🧮 时间复杂度分析
枚举空调状态:2M2^M2M(最多 1024 种)
每个状态内:
-
更新降温范围:O(M⋅区间长度)\mathcal{O}(M \cdot \text{区间长度})O(M⋅区间长度)
-
验证所有奶牛:O(N⋅牛栏长度)\mathcal{O}(N \cdot \text{牛栏长度})O(N⋅牛栏长度)
最大范围不超过 [1,100][1,100][1,100],所以总体复杂度大约为:O(2M⋅100⋅N)=O(1024⋅100⋅20)=2×106O(2^M ⋅100⋅N)=O(1024⋅100⋅20)=2×10^6O(2M⋅100⋅N)=O(1024⋅100⋅20)=2×106
参考代码
#include <bits/stdc++.h>
using namespace std;struct cow{int si , ti , ci; //范围为si~ti 降温至少ci
}a[29];struct air{int ai , bi , pi , mi; //范围ai~bi 降温能力pi 运行成本mi
}b[19];int main()
{int n , m;cin >> n >> m; //n头牛 m台空调for(int i = 0; i < n; i++)cin >> a[i].si >> a[i].ti >> a[i].ci;for(int i = 0; i < m; i++)cin >> b[i].ai >> b[i].bi >> b[i].pi >> b[i].mi;//枚举空调的使用情况int Mi = 1e9;for(int i = 0; i < (1 << m); i++){int cost = 0;vector<int>range(109); //range[i]:i处降温多少for(int k = 0; k < m; k++){if(1 << k & i) //第k台空调使用{cost += b[k].mi; //花费累加for(int j = b[k].ai; j <= b[k].bi; j++)range[j] += b[k].pi;}}//判断每一头牛是否满足题意bool check = true;for(int j = 0; j < n; j++){for(int l = a[j].si; l <= a[j].ti; l++){if(range[l] < a[j].ci)check = false;}}if(check)Mi = min(Mi , cost);}cout << Mi;return 0;
}