牛客算法周周练4 - 装备合成(三分、线性规划、贪心)
牛客算法周周练4 - 装备合成(三分、线性规划、贪心)
链接:https://ac.nowcoder.com/acm/contest/5505/E
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
牛牛有x件材料a和y件材料b,用2件材料a和3件材料b可以合成一件装备,用4件材料a和1件材料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
假设方案一做了m件装备,方案二做了n件装备,我们遍历m来求n,n=min((x-2m)/4, y-3m),三分m,求n+m的最大值
由于三分时返回的m+n是整数,注意下面的情况时check(mid1)==check(mid2)&&check(mid1)<check(R) ,L=mid1+1,而不是R=mid2-1
1 #include <bits/stdc++.h> 2 typedef long long LL; 3 #define pb push_back 4 const int INF = 0x3f3f3f3f; 5 const double eps = 1e-8; 6 const int mod = 1e9+7; 7 const int maxn = 1e5+10; 8 using namespace std; 9 10 int x, y; 11 int check(int m) 12 { 13 return m+min((x-2*m)/4, y-3*m); 14 } 15 16 int main() 17 { 18 #ifdef DEBUG 19 freopen("sample.txt","r",stdin); //freopen("data.out", "w", stdout); 20 #endif 21 22 int T; 23 scanf("%d",&T); 24 while(T--) 25 { 26 scanf("%d %d",&x,&y); 27 int L=0, R = min(x/2, y/3); 28 int ans = 0; 29 while(L<=R) 30 { 31 int mid1 = L+(R-L)/3, mid2 = R-(R-L)/3; 32 int res1 = check(mid1), res2 = check(mid2); 33 ans = max(res1, res2); 34 if(res1<res2||(res1==res2&&res1<check(R))) L = mid1+1; 35 else R = mid2-1; 36 } 37 printf("%d\n", ans); 38 } 39 40 return 0; 41 }
数学规划,高考的知识点,应该都不(wang)难(le)吧。。
具体的解法去看大佬的吧:https://blog.nowcoder.net/n/50e8388a544e429bb6deb9f876f715d5
看到还有大佬用贪心做的,妙啊,也写一下:
1、当x特别多时(x>4y),尽量用方案二,ans = y
2、当y特别多时(x/2 < y/3),尽量用方案一(方案二消耗一个y要消耗4个x),ans = x/2
3、两者没有明显差距时,我们根据两个式子 2x+3y和4x+y,可以看出合成一件装备必使用5个材料,同时最后总共消耗的x必是偶数,ans = (x+y)/5,如果s为奇数并且(x+y)%5==0,ans-1(除去x多3,y多2的情况)
1 #include <bits/stdc++.h> 2 typedef long long LL; 3 #define pb push_back 4 const int INF = 0x3f3f3f3f; 5 const double eps = 1e-8; 6 const int mod = 1e9+7; 7 const int maxn = 1e5+10; 8 using namespace std; 9 10 int main() 11 { 12 #ifdef DEBUG 13 freopen("sample.txt","r",stdin); //freopen("data.out", "w", stdout); 14 #endif 15 16 int T; 17 scanf("%d",&T); 18 while(T--) 19 { 20 LL x, y; //记得开LL 21 scanf("%lld %lld",&x,&y); 22 LL ans = 0; 23 if(x > 4*y) ans = y; //x特别多 24 else if(x*3 < y*2) ans = x/2; //y特别多即x/2 < y/3 25 else 26 { 27 ans = (x+y)/5; 28 if(x&1&&(x+y)%5==0) ans--; 29 } 30 printf("%lld\n", ans); 31 } 32 33 return 0; 34 }
-