[USACO2023-JAN-Bronze] T2 Air Cownditioning II 题解

一、

题目描述

Farmer John 的农场记录到夏天以来最热的气温,他需要一些方法来给他的奶牛降温。因此,他决定去投资购买一些空调。

Farmer John的N头牛(1≤N≤20)住在一个谷仓里,谷仓里包含了一排牛棚,每个牛棚对应编号为1…100。第i头牛占用了一个范围内的所有牛棚,范围从si到ti。不同奶牛之间占用的牛棚相互分开,不会重合。不同的奶牛有不同的降温要求,第i头牛要求降低至少ci,这意味着它占用的所有牛棚都必须降低至少ci度。

谷仓里有M台空调,编号从1…M (1≤M≤10). 开第i台空调需要的花费是mi(1≤mi≤1000),同时,这台空调能减低第ai到第bi个牛棚的温度。空调开启之后,它能减低它范围内所有牛棚pi度(1≤pi≤10^6)。不同空调控制的范围可能会重合。

运营一个农场不是个容易的事情,FJ的预算紧张。请帮FJ找到最少的费用,来确保每头奶牛的需求都能被满足。数据确保如果开了所有的空调,每头奶牛都能有满意的温度。

输入

第一行包含两个整数N和M。

接下来N行描述每头奶牛的情况,包含si,ti和ci。

接下来M行描述每台空调的情况,第i行包含ai,bi,pi和mi。

除了样例以外的其他所有输入,能确保M = 10.

输出

输出一个整数,表示最低的能让所有奶牛都满意的费用。

样例

输入
复制

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], [1,2]和 [6,9]这三台空调,花费的费用为 3+2+5=10.

二、分析

  1. M=10,方案数为2的M次方,最多1024个方案,dfs枚举创建方案。

  1. 每个空调的状态从 0 0 0 0 0 0 0 0 0 0 ~ 1 1 1 1 1 1 1 1 1 1。

  1. 每个牛棚位置需要降低温度存储在a数组,不同的空调状态每个牛棚位置降低点温度存储在b数组,比较是否满足牛棚降低温度的需要,寻找较小花费值。

三、代码

#include <bits/stdc++.h>
using namespace std;
const int N=110;
int n,m,ans=1e6;
int a[N],b[N],st[N],ed[N],val[N],cost[N];
//a:每个围栏需要降低的温度,b:开启空调围栏降低了的温度
int check(string subset) {
    int cur=0;
    memset(b,0,sizeof(b));
    for(int i=0;i<subset.size();i++){
        if(subset[i]=='1'){
            for(int j=st[i];j<=ed[i];j++){
                b[j]+=val[i];
            }
            cur+=cost[i];
        }
    }
    bool ok=true;
    for(int i=1;i<=100;i++){
        if(a[i]>b[i]){
            ok=false;
            break;
        }
    }
    if(ok) return cur;
    else return 1e6;
}
void build_subset(string curr) {
    if (curr.size() == m) {
        // 每一位代表一个空调的状态,所有空调的状态就位
        ans = min(ans, check(curr));
        // int t=check(curr);
        // cout<<ans<<' ' <<t<<endl;
        // if(ans>t)ans=t;
    } else {
        build_subset(curr + "1"); // 用
        build_subset(curr + "0"); // 不用
    }
}

int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        int x,y,z;scanf("%d%d%d",&x,&y,&z);
        for(int j=x;j<=y;j++) a[j]=z;
    }
    for(int i=0;i<m;i++){ //字符串从0开始,所以空调也是从0开始
        scanf("%d%d%d%d",&st[i],&ed[i],&val[i],&cost[i]);
        //ans+=cost[i];    //所有空调全部开启必是一解
    }
    build_subset("");
    printf("%d",ans);
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值