题目描述
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
牛牛有x件材料a和y件材料b,用2件材料a和3件材料b可以合成一件装备,用4件材料a和1件材料b也可以合成一件装备。牛牛想要最大化合成的装备的数量,于是牛牛找来了你帮忙。
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
输入描述:
输入包含t组数据 第一行一个整数t 接下来t行每行两个整数x,y
输出描述:
每组数据输出一行一个整数表示答案。
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
示例1
输入
5 4 8 7 6 8 10 100 4555 45465 24124
输出
2 2 3 50 13917
备注:
1<=t<=10000
1<=x,y<=1e9
一开始我忽视了数据量上手就以为是动态规划,就先写了个记忆化搜索
#include <iostream>
using namespace std;
int dp[1000][1000];
int process(int x, int y)
{
if (dp[x][y] != 0)
return dp[x][y];
if (x < 2 || y < 1)
return 0;
int p1 = 0, p2 = 0;
if (x >= 2 && y >= 3)
{
p1 = p1 + 1 + process(x - 2, y - 3);
}
if (x >= 4 && y >= 1)
{
p2 = p2 + 1 + process(x - 4, y - 1);
}
dp[x][y] = max(p1, p2);
return dp[x][y];
}
int main()
{
int T;
cin >> T;
while (T--)
{
int x, y;
cin >> x >> y;
int num = process(x, y);
cout << num;
}
return 0;
}
但重新看一下发现数据量竟达到10e+9,显然动态规划在此处不能使用,即使使用状态压缩,时间复杂度过高也会卡住
在讲解正解前,先介绍一下三分法
如图,当我们在寻找最小值或者最大值时,三分法就是一个不错的方法
分别取两边L,R,让后中间两个点mL,mR(mL=L+(R-L)/3,mR=R-(R-L)/3)
回到题目,可以发现当以第一种方式2a,3b合成m个,那么总共合成m+min((x-2a)/4,(y-3b)/1),然后我们可以发现这里
此时我们可以发现这里就存在一个最大值,与前面学的三分挂钩
代码如下
#include <iostream>
using namespace std;
int sum(int m,int x, int y)
{
return m + min((x - 2 * m) / 4, y - 3 * m); //这里b材料➗1省略
}
int main()
{
int T; //次数
cin >> T;
int x, y;
while (T--)
{
cin >> x >> y;
int L = 0, R = x / 2; //这里右边直接取两种合成方案用材料a的最大值
while (L < R)
{
int mL = L + (R - L) / 3;
int mR = R - (R - L) / 3;
if (sum(mL, x, y) > sum(mR, x, y)) //类似上边函数取值操作
R = mR - 1;
else
L = mL + 1;
}
cout << sum(L, x, y) << endl;
}
return 0;
}