bzoj3874 [ AHOI2014 ] -- 爬山算法
Posted gjghfd
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3874 [ AHOI2014 ] -- 爬山算法相关的知识,希望对你有一定的参考价值。
不知道为什么,用模拟退火就WA了。。。
显然如果知道了总共购买几次,就可以贪心地求出答案。那么套个爬山就行了。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<cstring> 5 #include<algorithm> 6 #include<cstdlib> 7 #include<cmath> 8 using namespace std; 9 #define N 210 10 #define ll long long 11 struct Node{ 12 ll p,s; 13 }a[N],A[N],b[N]; 14 ll m,Ans,x,y,C,f,N2; 15 int i,j,k,n,Cnt,Tot; 16 inline ll _Min(ll x,ll y){return x<y?x:y;} 17 inline bool Cmp1(Node a,Node b){ 18 return a.s>b.s||(a.s==b.s&&a.p<b.p); 19 } 20 inline bool Cmp2(Node a,Node b){ 21 return a.p<b.p||(a.p==b.p&&a.s>b.s); 22 } 23 inline double Getrand(){ 24 return rand()%1000/1000.0; 25 } 26 inline ll Calc(ll x){ 27 if(x==0)return 0; 28 ll S=m-x*f,A=0,d=0,y; 29 for(int i=1;i<=n;i++){ 30 y=_Min(S/a[i].p/x,a[i].s-d+1); 31 S-=x*y*a[i].p; 32 d+=y;A+=x*y; 33 if(d<=a[i].s){ 34 y=S/a[i].p; 35 A+=y; 36 break; 37 } 38 } 39 if(A>Ans)Ans=A; 40 return A; 41 } 42 inline void HC(double T){ 43 for(x=1,Ans=Calc(x);T>1;T*=0.9){ 44 y=x+(ll)(T*(Getrand()*2-1)); 45 if(y<1)continue; 46 C=Calc(y)-Calc(x); 47 if(C>0)x=y; 48 } 49 } 50 int main() 51 { 52 srand(1000000007); 53 scanf("%lld%lld%d",&m,&f,&n); 54 for(i=1;i<=n;i++)scanf("%lld%lld",&A[i].p,&A[i].s); 55 sort(A+1,A+n+1,Cmp1); 56 b[Cnt=1]=A[1]; 57 for(i=2;i<=n;i++)if(A[i].s!=A[i-1].s)b[++Cnt]=A[i]; 58 sort(b+1,b+Cnt+1,Cmp2); 59 a[Tot=1]=b[1]; 60 for(i=2;i<=Cnt;i++)if(b[i].p!=b[i-1].p)a[++Tot]=b[i]; 61 n=Tot; 62 HC(m/(double)f); 63 printf("%lld",Ans); 64 return 0; 65 }
以上是关于bzoj3874 [ AHOI2014 ] -- 爬山算法的主要内容,如果未能解决你的问题,请参考以下文章
bzoj3874&2832 [Ahoi2014]宅男计划 模拟退火,三分