挑战程序设计竞赛 2.2 一往直前!贪心法
【Summarize】
1.考虑整体性的时候可以从局部最优考虑,即通过前后关系列不等式
2.拟阵的遗传性质通常体现在物品可否倍数拆分
POJ 2376:Cleaning Shifts
/* 用区间去覆盖长为T的整条线段,求最少的区间数量 */ #include <cstdio> #include <algorithm> using namespace std; int d=0,pos,x,y,n,T,a[1000005]; int main(){ scanf("%d%d",&n,&T); for(int i=1;i<=n;i++){ scanf("%d%d",&x,&y); a[x]=max(a[x],y+1); }a[T+1]=T+1; for(int i=2;i<=T;i++)a[i]=max(a[i-1],a[i]); for(pos=1;a[pos]!=pos;pos=a[pos])d++; if(pos!=T+1)puts("-1");else printf("%d\n",d); return 0; }
POJ 1328:Radar Installation
/* 在二维平面内给出一些点,现在允许你画圆心在x周上,半径固定的圆, 求最小的圆个数,使得能将所有给出的点覆盖 */ #include <cstdio> #include <algorithm> #include <cmath> using namespace std; int n,Cas=0,flag,cnt; double r,x,y; struct data{double l,r;}p[2005],tmp; bool cmp(data a,data b){return a.l<b.l;} int main(){ while(scanf("%d%lf",&n,&r),n||r){ flag=0; for(int i=0;i<n;i++){ scanf("%lf%lf",&x,&y); if(fabs(y)>r)flag=1; else{ p[i].l=x-sqrt(r*r-y*y); p[i].r=x+sqrt(r*r-y*y); } }printf("Case %d: ",++Cas); if(flag){puts("-1");} else{ cnt=1; sort(p,p+n,cmp); tmp=p[0]; for(int i=1;i<n;i++){ if(p[i].l>tmp.r){ cnt++; tmp=p[i]; }else if(p[i].r<tmp.r)tmp=p[i]; }printf("%d\n",cnt); } }return 0; }
POJ 3190:Stall Reservations
/* 每头牛都有一段固定长度的时间要吃草,不能和别的牛重叠, 现在问需要多少草槽才能满足所有牛的需求 */ #include <cstdio> #include <utility> #include <queue> #include <algorithm> using namespace std; struct data{int r,id;}tmp; struct data1{int l,r,id;}p[50005]; int ans[50005],n,cnt; bool operator<(data a,data b){return a.r>b.r;} bool cmp(data1 a,data1 b){return a.l<b.l;} int main(){ priority_queue<data> Q; scanf("%d",&n); for(int i=0;i<n;i++)scanf("%d%d",&p[i].l,&p[i].r),p[i].id=i; sort(p,p+n,cmp); ans[p[0].id]=cnt=1; tmp.id=1;tmp.r=p[0].r; Q.push(tmp); for(int i=1;i<n;i++){ tmp=Q.top(); if(tmp.r<p[i].l){ Q.pop(); tmp.r=p[i].r; ans[p[i].id]=tmp.id; Q.push(tmp); }else{ ans[p[i].id]=++cnt; tmp.r=p[i].r; tmp.id=cnt; Q.push(tmp); } }printf("%d\n",cnt); for(int i=0;i<n;i++)printf("%d\n",ans[i]); return 0; }
POJ 2393:Yogurt factory
/* 每周生产的牛奶所需要的费用为ci,保存每单位的牛奶每周需要费用为s, 现在告诉你每周需要的牛奶数量,求最小的花费 */ #include <cstdio> #include <algorithm> using namespace std; int n,s,c,y; long long ans; int main(){ scanf("%d%d",&n,&s); int cost=5000; for(int i=1;i<=n;i++){ scanf("%d%d",&c,&y); cost=min(cost+s,c); ans+=cost*y; }printf("%lld\n",ans); return 0; }
POJ 1017:Packets
/* 箱子的长宽是6*6,现在有一些6*6,5*5,4*4,3*3,2*2,1*1的物品 问最少需要多少箱子才能把他们全都装下 */ #include <cstdio> int ans,a1,a2,a3,a4,a5,a6,lft; int main(){ while(~scanf("%d%d%d%d%d%d",&a1,&a2,&a3,&a4,&a5,&a6),a1+a2+a3+a4+a5+a6){ ans=(a5+a6+a4)+(a3+3)/4; lft=a4*5; if(a3%4)lft+=7-2*(a3%4); if(a2>lft)ans+=(a2-lft+8)/9; lft=ans*36-a6*36-a5*25-a4*16-a3*9-a2*4; if(a1>lft)ans+=(a1-lft+35)/36; printf("%d\n",ans); }return 0; }
POJ 3040:Allowance
/* 给出你所拥有的面值不同的钞票数量,问你可以支付多少次大于等于c的费用 钞票的面值为倍数关系(倍数关系可满足拟阵的遗传性质,因此贪心方法成立) */ #include <cstdio> #include <algorithm> #include <utility> #include <climits> #include <cstring> using namespace std; #define ff first #define ss second const int INF=INT_MAX; pair<int,int> p[25]; int n,C,ans,tag[25]; int main(){ scanf("%d%d",&n,&C); for(int i=1;i<=n;i++)scanf("%d%d",&p[i].ff,&p[i].ss); sort(p+1,p+n+1); while(n&&p[n].ff>=C)ans+=p[n--].ss; while(1){ int s=C; memset(tag,0,sizeof(tag)); for(int i=n;i;i--){ int t=s/p[i].ff; t=min(t,p[i].ss); s-=t*p[i].ff; tag[i]+=t; } if(s){ for(int i=1;i<=n;i++){ if(p[i].ss&&p[i].ff>=s){ s=-0; tag[i]++; break; } } }if(s>0)break; int tmp=INF; for(int i=1;i<=n;i++){ if(tag[i])tmp=min(tmp,p[i].ss/tag[i]); }ans+=tmp; for(int i=1;i<=n;i++)p[i].ss-=tmp*tag[i]; }printf("%d\n",ans); return 0; }
POJ 1862:Stripies
/* 质量为m1和m2的物品相碰之后。质量变为2*sqrt(m1*m2),请你决定一种碰撞顺序 使得碰撞之后答案最小。 */ #include <cstdio> #include <algorithm> #include <cmath> using namespace std; double a[105]; int n; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%lf",&a[i]); sort(a+1,a+n+1); for(int i=n-1;i;i--)a[n]=2*sqrt(a[n]*a[i]); printf("%.3f\n",a[n]); return 0; }
POJ 3262:Protecting the Flowers
/* 一些牛在花园啃话,每时间单位啃花di单位,将一头牛送牛棚再回来需要时间2*ti 请最小化花朵被啃食的数量。 若i和j两头牛位置相邻,则i在j前面消耗为(T+ti)*dj+T*di j在i前面消耗为(T+tj)*di+T*dj 则i和j两头牛i牛在送回顺序中排在前面答案更优的充要条件为di*tj>dj*ti */ #include <cstdio> #include <algorithm> using namespace std; int n; struct data{int t,d;}p[100010]; bool cmp(data a,data b){return a.d*b.t>b.d*a.t;} int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d%d",&p[i].t,&p[i].d); sort(p+1,p+n+1,cmp); long long ans=0,T=0; for(int i=1;i<=n;i++){ ans+=T*p[i].d; T+=p[i].t*2; }printf("%lld\n",ans); return 0; }
愿你出走半生,归来仍是少年