poj 3266 Cow School 分数规划

来源:互联网 发布:SQL字段保留两位数 编辑:程序博客网 时间:2024/06/15 03:36
 
分类: 分数规划 240人阅读 评论(0) 收藏 举报

这个题目难度非常大,首先对于老师的一种方案,应用分数规划的一般做法,求出所有的c=t-rate*p,如果没有选择的c值中的最大值比选择了的c值中的最小值大,那么这个解是可以改进的。

那么问题就转化成了怎么求最小的c和最大的c。

t-rate*p 求这种类型的最值,并且rate是单调的,那么就可以考虑利用斜率优化的那种办法来维护决策点。

考虑两个决策点,得到ti-tj>rate(pi-pj)  但是这个pi pj的大小不能确定,我们知道可以利用斜率优化的问题不仅仅要rate单调,还需要pi 单调 这个时候我们需要利用题目中的条件,题目中保证了t/p单调,根据这个条件,可以推出求两种最值的时候都只有单调的p才是有可能成为决策点的。那么就可以按照斜率优化步骤来解题了。一个是用单调栈维护,另外一个利用单调队列维护。

[cpp] view plaincopy
  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <cstring>  
  4. #include <algorithm>  
  5. using namespace std;  
  6. const int maxn=5e4+9;  
  7. double high[maxn],low[maxn];  
  8. long long sumt[maxn],sump[maxn];  
  9. struct D  
  10. {  
  11.     long long t,p;  
  12.     bool operator <(const D & xx) const  
  13.     {  
  14.         return t*xx.p>xx.t*p;  
  15.     }  
  16. }test[maxn];  
  17. int que[maxn];  
  18.   
  19. bool chk(int i,int j,int t,int s)  
  20. {  
  21.     long long a=(test[i].t-test[j].t)*(test[t].p-test[s].p);  
  22.     long long b=(test[t].t-test[s].t)*(test[i].p-test[j].p);  
  23.     return a>b;  
  24. }  
  25.   
  26. bool chk2(int i,int j,long long t,long long p)  
  27. {  
  28.     long long a=(test[i].t-test[j].t)*p;  
  29.     long long b=t*(test[i].p-test[j].p);  
  30.     return a>b;  
  31. }  
  32. int main()  
  33. {  
  34.     int n;  
  35.     while(scanf("%d",&n)!=EOF)  
  36.     {  
  37.         for(int i=1;i<=n;i++)  
  38.         scanf("%lld %lld",&test[i].t,&test[i].p);  
  39.         sort(test+1,test+1+n);  
  40.   
  41.         for(int i=1;i<=n;i++)  
  42.         {  
  43.             sumt[i]=sumt[i-1]+test[i].t;  
  44.             sump[i]=sump[i-1]+test[i].p;  
  45.         }  
  46.   
  47.         int front=1,end=0;  
  48.         for(int i=1;i<=n;i++)  
  49.         {  
  50.             while(end>=front&&test[i].p>=test[que[end]].p)  
  51.             end--;  
  52.             while(end>front&&chk(que[end],i,que[end-1],que[end]))  
  53.             end--;  
  54.             que[++end]=i;  
  55.             while(front<end&&chk2(que[front],que[front+1],sumt[i],sump[i])==1)  
  56.             front++;  
  57.             int u=que[front];  
  58.             low[i]=test[u].t-(double)sumt[i]/sump[i]*test[u].p;  
  59.         }  
  60.         int top=0;  
  61.         for(int i=n;i>=1;i--)  
  62.         {  
  63.             while(top>0&&test[i].p<=test[que[top]].p)  
  64.             top--;  
  65.             while(top>1&&chk(i,que[top],que[top],que[top-1]))  
  66.             top--;  
  67.             que[++top]=i;  
  68.             while(top>1&&chk2(que[top],que[top-1],sumt[i-1],sump[i-1])==0)  
  69.             top--;  
  70.             int u=que[top];  
  71.             high[i]=test[u].t-(double)sumt[i-1]/sump[i-1]*test[u].p;  
  72.         }  
  73.         int ans=0;  
  74.         for(int i=1;i<n;i++)  
  75.         if(high[i+1]>low[i])  
  76.         ans++;  
  77.         cout<<ans<<endl;  
  78.         for(int i=n-1;i>=1;i--)  
  79.         if(high[i+1]>low[i])  
  80.         printf("%d\n",n-i);  
  81.     }  
  82.     return 0;  
  83. }  
0 0
原创粉丝点击