Poj 2393
题意:酸奶厂可以存放任意数量的酸奶,每单位酸奶每周存储需要S元。第i周生产每单位酸奶要ci元,需要送yi单位酸奶给客户。问酸奶厂最低花费多少使得能按时给顾客送奶。
多刷题真的是很有用啊,没想到扇贝杯的时候就出了一道跟这差不多的题,但是我long long 用错了只得了80分
感觉自己真真是猪了,很多东西都重复计算了,价格一定是在上周的最小价上+S或者是本周生产的啊
突然感觉自己既想复杂又想简单了,所以有点懵。。orz
#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
typedef long long LL;
LL ans;
int n,s;
const int N=1e4+10;
int cost[N],del[N];
int main()
{
//freopen("in.txt","r",stdin);
cin>>n>>s;
for(int i=1;i<=n;++i)
cin>>cost[i]>>del[i];
for(int i=2;i<=n;++i)
cost[i]=min(cost[i],cost[i-1]+s);
for(int i=1;i<=n;++i)
ans+=cost[i]*del[i];
cout<<ans<<endl;
return 0;
}
poj 1017 packets
题意:有1*1*h 2*2*h ... 6*6*h规格的箱子,分别给出它们的数量,问用6*6*h的箱子去装这些箱子,最少需要多少个箱子
我的代码写的实在是太冗长了,而且还wa了,窒息
三处改进代码:
1、向上取整 (a[3]+3)/4 我分类讨论的来着_(:з」∠)_
2、 a[1]=max(0,a[1]-4*(5*a[4]-a[2])); 我用了冗长的循环 和分类_(:з」∠)_
3、考虑填充3*3剩下的位置时,可填充的2*2和1*1与3*3的个数有线性关系,我是一个个分类的_(:з」∠)_
多动点脑子,少写点废话
另一种思路,做加法不要做减法,把这么多箱子最多能放多少个算出来,会简单很多。。。
poj 3040 Allowance
题意:Fj有N种面值的硬币,面值V,数量B,Fj想每周都给奶牛至少发C元的工资,问Fj最多能发多少周的工资。
每个周都要尽可能地给刚好C元,如果凑不到C元,那么就拿小的去补
贪心吧贪心策略又想不到,看了贪心策略吧代码又写得和shi一样
cnt数组记录要凑到不小于C,需要每种面值多少个,拿总数除以它,就知道这样能分配多少周,以节省时间
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,c;
const int N=25;
struct money
{
int v;
int b;
}m[N];
int cnt[25];
bool cmp(money p,money q)
{
return p.v>q.v;
}
int main()
{
scanf("%d%d",&n,&c);
int ans=0;
for(int i=1;i<=n;++i)
{
scanf("%d%d",&m[i].v,&m[i].b);
}
sort(m+1,m+1+n,cmp);
int i;
for(i=1;i<=n;++i)
{
if(m[i].v>=c)
ans+=m[i].b;
else
break;
}
if(i==n+1)
{
printf("%d\n",ans);
return 0;
}
while(true)
{
memset(cnt,0,sizeof(cnt));
int sum=c;
for(int j=i;j<=n;++j)
{
if(m[j].b&&sum>0)
{
cnt[j]+=min(m[j].b,sum/m[j].v); //需要的和剩下的小值,不能超过c
sum-=cnt[j]*m[j].v;
}
}
if(sum>0)
{
for(int j=n;j>=i;--j)
{
if(m[j].b&&sum>0)
{
int tmp=min(m[j].b-cnt[j],(sum+m[j].v-1)/m[j].v); //上面一轮取下来不够,就拿最小的去补,这样保证最小损失(大于c的部分最小)
if(tmp>0) //因为这里是允许超过c的,所以是向上取 注意cnt要>=0
{
sum-=tmp*m[j].v;
cnt[j]+=tmp;
}
}
}
}
if(sum>0)
break;
int tmp=0x3f3f3f3f;
for(int j=i;j<=n;++j)
{
if(cnt[j]) //忘了这一行犯了除零错误
tmp=min(tmp,m[j].b/cnt[j]);
}
ans+=tmp;
for(int j=i;j<=n;++j)
{
if(cnt[j])
m[j].b-=tmp*cnt[j];
}
}
printf("%d\n",ans);
return 0;
}
poj 1862 哈夫曼编码、优先权队列
可以看出来,越先乘的数开次方次数越多,也就越小,因此每次选择最大的两个数
poj 3262 protecting flowers
题意:N只牛进了FJ的花园,将第i头牛送回去往返时间为2*Ti,若她被留在花园里,每分钟破坏di的花,问Fj合理安排送牛的顺序,破坏的花数最少?
假设牛A,送走a1,毁坏b1;牛B,送走a2,毁坏b2;
先送牛A后送牛B,损失2*a1*b2
先送牛B后送牛A,损失2*a2*b1
如果先送牛A更优,即a1*b2<a2*b1,即a1/b1<a2/b2,先送比值小的,为了避免余数等,直接用式子a1*b2<a2*b1排序即可
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
int n;
const int N=1e5+10;
struct cow
{
int t;
int d;
}c[N];
bool cmp(cow p,cow q)
{
return p.t*q.d<q.t*p.d;
}
int main()
{
scanf("%d",&n);
int des=0;
for(int i=1;i<=n;++i)
{
scanf("%d%d",&c[i].t,&c[i].d);
des+=c[i].d;
}
sort(c+1,c+1+n,cmp);
LL ans=0;
for(int i=1;i<=n;++i)
{
des-=c[i].d; //花园里的牛每分钟破坏花的数目
ans+=2*c[i].t*des;
}
printf("%lld\n",ans);
return 0;
}