题目链接
(水题)
题意:已知存在A,B,AB三种披萨,价格分别为a,b,c,问你最少花多少钱可以买到最少x个A披萨,y个B披萨。
题解:主要就几种情况,取个最小值就行。(注意AB披萨是一半A一半B)
代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn = 1e5 + 500;
int main() {
ll a, b, c, x, y;
while (~scanf("%lld%lld%lld%lld%lld", &a, &b, &c, &x, &y)) {
ll ans = x*a + y*b;
ll MIN = min(x, y);
ll MAX = max(x, y);
ans = min(ans, 2 * MIN*c + (x - MIN)*a + (y - MIN)*b);
ans = min(ans, 2 * MAX*c);
cout << ans << endl;
}
return 0;
}
(贪心)
题意:已知一个环形道路,周长为c,现在告诉你你在x=0的位置,环形道路上存在n个点x[i]有能量为v[i]的食物,并且你每走一步消耗1点能量(这里自身能量可以为负),求你在这环形道路上走时,某一时刻自身拥有的最大能量是多少。
题解:因为是一个环,我们可以正向走也可以反向走,同时还可以先正向走到某个点 i 再回到x=0处然后反向走到某个大于 i的点,也可以先反向走到某个点 i 再回到x=0处然后正向走到某个小于 i 的点,在这4种情况中获得的最大能量就是答案了。
前面2种情况直接一路扫过去就行,后面2种情况需要事先预处理出2个数组,一个是正向与反向走到 i 点能获得的最大能量 dp[0/1][i],另一个是正向和反向走到 i 点然后再回到x=0处所获得的能量g[0/1][i].
那么后面2种情况对于走到某个点能获得的最大能量就是max(g[0][i] + dp[1][i + 1] , g[1][i] + dp[0][i - 1] ) ;
(具体过程看代码有注释,同时当最终答案为负数也可以选择不走)
代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define inf 0x3f3f3f3f3f3f3f
#define ll long long
const int maxn = 1e5 + 500;
ll dp[2][maxn];//dp[0][i]表示正向走到i点获得的最大能量,dp[1][i]为反向...
ll g[2][maxn];//g[0][i]表示正向走到i点回到x=0位置所拥有的能量,g[1][i]反之...
ll x[maxn], v[maxn];
ll n, c, sum;
int main() {
scanf("%lld%lld", &n, &c);
for (int i = 1; i <= n; i++) scanf("%lld%lld", &x[i], &v[i]);
for (int i = 0; i <= n + 1; i++)dp[0][i] = dp[1][i] = -inf;
for (int i = 1; i <= n; i++) {//正向遍历
sum += v[i];
dp[0][i] = max(dp[0][i - 1], sum - x[i]);
g[0][i] = sum - 2 * x[i];
}
sum = 0;
for (int i = n; i >= 1; i--) {//反向遍历
sum += v[i];
dp[1][i] = max(dp[1][i + 1], sum - (c - x[i]));
g[1][i] = sum - 2 * (c - x[i]);
}
ll ans = max(dp[0][n], dp[1][1]);
for (int i = 1; i <= n; i++) {
ans = max(ans, g[0][i] + dp[1][i + 1]);
ans = max(ans, g[1][i] + dp[0][i - 1]);
}
printf("%lld\n", ans > 0 ? ans : 0);//若ans<0可以选择不走
return 0;
}