POJ 2393 Yogurt factory~贪心详解

来源:互联网 发布:中传在线 网络教育登录 编辑:程序博客网 时间:2024/04/27 13:53

这道题题意为酸奶厂要生产N周的酸奶,第i周生产每单位的牛奶需要c_i元,需要y_i单位的牛奶。酸奶厂有一个仓库,仓库储存费为每周每单位的牛奶需要花费S元。求生产牛奶的最少花费。

一开始做这道题,思路是开一个二维数组,第i行记录从第0周一直到第i周生产y_i单位牛奶所需费用,然后再找出最小值来加。这个方法是特别笨的一个方法,既超时又超内存,说多都是泪啊···不过经过修改把内存降下来了,二维数组变成一维,省去了很多不必要的内存空间。而TLE没有解决。

然后看别人的讨论,看到了:

*mincost[i]为刚好通过i周的最小花费,mincost[i]=mincost[i-1]+produce[i][y[i]];produce[i][y[i]]表示前i周生产y[i]单位酸奶并存储到第i周所需的最小花费produce[i][y[i]]一定是从某一个周生产的;设为j周,produce[i][y[i]]=w[j]*y[i]+s*(i-j)*y[i]=y[i]*(w[j]+s*(i-j));即问题在于寻找最小的(w[j]+s*(i-j))发现这个式子与当前所在的周数无关(任取两周a,b.发现a优于b的不等式的成立与i无关),所以就比较之前最优的周和当前周就可以了

于是再度修改函数,终于把一层for循环也去掉了,复杂度变为O(n),一试果真通过啦~

贴上代码:

#include<iostream>#include<algorithm>#include<cstdio>using namespace std;int n,s;long long b[10001];int a[10001][2];int vis;long long sum;void pre(int x){int i;long long temp=a[x][0]*a[x][1];if(temp>a[vis][0]*a[x][1]+s*a[x][1]*(x-vis)){temp=a[vis][0]*a[x][1]+s*a[x][1]*(x-vis);}elsevis=x;//记录最优周b[x]=temp;}int main(void){int i,j;while(scanf("%d%d",&n,&s)!=EOF){for(i=0;i<n;i++)for(j=0;j<2;j++)cin>>a[i][j];sum=0;vis=0;sum+=a[0][0]*a[0][1];for(i=1;i<n;i++)pre(i);for(i=1;i<n;i++)sum+=b[i];cout<<sum<<endl;}return 0;}