装备合成

链接:

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

牛牛有{x}x件材料{a}a和{y}y件材料{b}b,用{2}2件材料{a}a和{3}3件材料{b}b可以合成一件装备,用{4}4件材料{a}a和{1}1件材料{b}b也可以合成一件装备。牛牛想要最大化合成的装备的数量,于是牛牛找来了你帮忙。

输入描述:

输入包含t组数据
第一行一个整数t
接下来t行每行两个整数x,y
输出描述:
每组数据输出一行一个整数表示答案。
示例1
输入
复制

5
4 8
7 6
8 10
100 4555
45465 24124

输出
复制

2
2
3
50
13917

备注:
1<=t<=10000
1<=x,y<=1e9

题解:

两个做法一个三分,一个贪心

三分的做法


我们都知道 二分查找 适用于单调函数中逼近求解某点的值。
如果遇到凸性或凹形函数时,可以用三分查找求那个凸点或凹点。
假设A装备做了m件,B装备做了n件,我们固定m来求n
n=min( (x-2m)/4 , y-3m )就是看做完m剩下的材料,还能做多少个n,然后返回n+m,不断三分求出n+m的峰值,即最大值

代码:

#include<bits/stdc++.h>
using namespace std;
int x,y;
int check(int n){
    return n+min((x-2*n)/4,y-3*n);
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        cin>>x>>y;
        int l=0;
		int r=min(x/2,y/3);//目前 的x和y最多能做多少个m 
        while(l<r){
            int mid1=l+(r-l)/3; 
            int mid2=r-(r-l)/3;
            if(check(mid1)>check(mid2))r=mid2-1;
            else l=mid1+1;
        }
        printf("%d\n",check(l));
    }
    return 0;
}

贪心的做法:

1.材料a特别多时,尽量用a来合成装备2,满足a>4b,b为多少就可以做多少件
2材料b特别多时,尽量用b来合成装备1,要满足3
a<2*b,a为多少,就可以做a/2件
3.当两者差不多时,我们结合题目中两个式子:2a+3b=1,4a+b=1,我们可以得到a=1/5,b=1/5,也就是合成一件装备a+b必须是5的倍数,而且观察式子,a还必须是偶数。
所以如果a不是偶数,或者(a+b)不是5的倍数,结果就要减一
(相当于去除多余的材料,构成a为偶数,a+b为5倍数的情况)

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int t;
ll a,b;
int main() {
    cin>>t;
    while(t--) {
        cin>>a>>b;
        if(a>(b<<2)) printf("%lld\n",b);
        else if(a*3<(b<<1)) printf("%lld\n",(a>>1));
        else {
            ll sum=(a+b)/5;
            if(a&1&&(a+b)%5==0) --sum;
            printf("%lld\n",sum);
        }
    }
}
posted @ 2020-05-01 17:39  回归梦想  阅读(82)  评论(0编辑  收藏  举报