(p245)分数背包(O(n))

来源:互联网 发布:佳能打印机 mac 编辑:程序博客网 时间:2024/06/05 03:04

思路请参考:http://blog.csdn.net/mishifangxiangdefeng/article/details/7748435

写起来还是挺麻烦的

复杂度为On的原因主要就是1+1/2+1/4+1/8....=2

#include<stdio.h>#include<stdlib.h>#define max 1000float v[max+1]={0,60,100,120};int w[max+1]={0,10,20,30},W=50,n=3;struct item{float vpw;int i;};int swap(struct item m[],int a,int b){struct item tmp;tmp=m[a];m[a]=m[b];m[b]=tmp;return 0;}int partition(struct item m[],int l,int r,int *j,int *k)//类似与快排,*j表示数组最后一个>的下标,*k表示最后一个=的下标{int mid=(l+r)/2,i,tj=l-1,tk=l-1;float x=m[mid].vpw;for (i=l;i<=r;i++)if (m[i].vpw>x){tj++;tk++;swap(m,tj,tk);swap(m,tj,i);}elseif (m[i].vpw==x){tk++;swap(m,tk,i);}*j=tj;*k=tk;return 0;}float Select(struct item m[],int W,int l,int r){if (l==r)return l;int j,k;partition(m,l,r,&j,&k);int i,sj=0,sk=0,sr=0;for (i=l;i<=j;i++)sj+=w[m[i].i];sk=sj;for (i=j+1;i<=k;i++)sk+=w[m[i].i];sr=sk;for (i=k+1;i<=r;i++)sr+=w[m[i].i];if (W>sr)return r;elseif (W>sk)return Select(m,W-sk,k+1,r);elseif (W>sj)return Select(m,W-sj,j+1,k);elsereturn Select(m,W,l,j);}int main(void){struct item m[max+1];int i;for (i=1;i<=n;i++){m[i].vpw=v[i]/w[i];m[i].i=i;}int l;l=Select(m,W,1,n);float sv=0;int sw=0;for (i=1;i<l;i++){sv+=v[m[i].i];sw+=w[m[i].i];}if (sw+w[m[i].i]>W)sv+=(W-sw+0.0)/w[m[i].i]*v[m[i].i];elsesv+=v[m[i].i];printf("%f\n",sv);return 0;}


0 0
原创粉丝点击