青于蓝庄园的水管

题目描述:

青于蓝庄园有很多高智商的奶牛,他们以帮助雇主解决问题获取高额报酬。

这次的雇主要求他们解决这样的问题:把水从池塘运输到牛棚里,池塘和牛棚相距D个单位。它们有P根水管,每根水管由2个整数来描述:水管长度Li,最大流量Ci。

水管可以依次连接构成一条运输管道(下水道?),那么这条运输管道的流量就是构成这条管道的所有水管中最小的一个流量。

但是,要让水从池塘通过运输管道流到牛棚里,管道的长度必须恰好等于池塘和牛棚的距离(也就是说,水管长度Li之和为D)!

现在只要求构造一条运输管道,求其最大流量。

输入:

包含两行,第1行:两个整数,D(7≤D≤100,000)和P(1≤P≤350);
第2...P+1行:每行两个整数Li和Ci(0≤Li, Ci≤224)。

输出:

一行仅一个整数,表示最大流量。

题解:

对于01背包问题的递归解法,一般对数据的个数有严格的要求,一般(n<=25),而这道题水管的根数远远大于25,所以得进行优化处理。

很显然,这么多水管,不选择的相对较多,所以选与不选之间,把不选放在前面比较优秀。

另外当选择的新水管,一定要不低于前面已经得到的答案(水管直径),否则就是徒劳。

STD:

#include <bits/stdc++.h>

using namespace std;
 
int  d, n, maxn, l[400], c[400];
 
void dfs(int dep, int sum, int last)  //三个参数分别是:第几根水管, 总的长度, 前面dep-1根水管的最小横截面的直径。
{
    if (last < maxn) return;//当选择的新水管,一定要不低于前面已经得到的答案(水管直径),否则就是徒劳。
    if (dep > n)
    {
        if (sum == d) maxn = max(maxn, last);
    }
    else
    {
        dfs(dep + 1, sum, last);    //不选优先处理
        if (sum + l[dep] <= d) dfs(dep + 1, sum + l[dep], min(last, c[dep]));
    }
}
 
int main()
{  
    cin >> d >> n;
    for (int i = 1; i <= n; i++)
        cin >> l[i] >> c[i];
    dfs(1, 0, INT_MAX); 
    cout << maxn << endl;
    return 0;
}
posted @ 2023-12-19 12:18  陆留生信奥艺术  阅读(89)  评论(0)    收藏  举报