题解 P6769 【[USACO05MAR]Yogurt factory 奶酪工厂】
O(n^2) 贪心算法
思路
贪心告诉我们“只看眼下”,所以我们把
按照贪心的思路,对于第
原因很简单,因为对于任意的
代码实现
具体实现的方法见代码(有具体注释与代码分析):
#include <bits/stdc++.h>
using namespace std;
int need[10001],cost[10001];
//need[i]表示第i天要上交的奶酪数
//cost[i]表示第i天买奶酪的花费
int n,S;
int main()
{
cin>>n>>S;
for(int i=1; i<=n; i++)
cin>>cost[i]>>need[i];
int Min;
long long ans=0;//记得开longlong
for(int i=1; i<=n; i++)//将每一天分开讨论
{
Min=INT_MAX;//将Min定义成最大值
for(int j=1; j<=i; j++)//寻找最优的j
Min=min(Min,cost[j]+S*(i-j));
//第j天的一个单位的奶酪放置到第i天的花费:
//第j天买来奶酪的花费(cost[j]),加上存储i-j天的花费(S*(i-j))
ans+=Min*need[i];//累加每天的最小花费
}
cout<<ans;
return 0;
}
到目前为止,我们就已经可以A掉本题了。但是
答案是肯定的。
O(n) 贪心优化算法
优化思路
贪心方法依然不变,现考虑对于第
不难发现,对于任意的
所以,我们只需要拿第
优化代码实现
具体实现的方法见代码(改动地方有详细注释):
#include <bits/stdc++.h>
using namespace std;
int need[10001],cost[10001];
int n,S;
inline int read() //以字符串形式读入数字可提速
{
int x=0;
char c=getchar();
for(; c<'0' || c>'9'; c=getchar());
for(; c<='9' && c>='0'; c=getchar())
x=(x<<3)+(x<<1)+c-'0'; //位运算优化即x*8+x*2=x*10
return x;
}
int main()
{
n=read(),S=read();
for(int i=1; i<=n; i++)
cost[i]=read(),need[i]=read();
int Min=INT_MAX-S;//此处减去S是为了防止爆精度
long long sum=0;
for(int i=1; i<=n; i++)
{
Min=min(Min+S,cost[i]);
//前一天最优的j在当天的花费:Min+S
//当天花费:cost[i]
sum+=Min*need[i];
}
cout<<sum;
return 0;
}
Tips:
-
INT_MAX 是 int 型下的最大整数,即
2^{32} ; -
题面良心地提到:
注意,答案可能超过 32 位长整型。
所以别忘了开 long long。
- 空间上的优化:在优化算法中,计算第
i 天的费用时,我们只用到了 cost 和 need 数组的第i 个元素。所以我们可以边读入边处理,将空间复杂度优化到O(1) 。