01分数规划.docx
- 文档编号:23657582
- 上传时间:2023-05-19
- 格式:DOCX
- 页数:20
- 大小:27.25KB
01分数规划.docx
《01分数规划.docx》由会员分享,可在线阅读,更多相关《01分数规划.docx(20页珍藏版)》请在冰豆网上搜索。
01分数规划
pku3621sightseeingcows解题报告
题意:
求存在一个环路,所有的点权之和/所以的边权之和最大是多少?
算法:
此题是对01分数规划的应用,那么首先明白01分数规划的思想.
01分数规划的思想的描述如下:
令c=(c1,c2,…,cn)和d=(d1,d2,…,dn)为n维整数向量,那么一个0-1分数规划问题用公式描述如下:
FP:
最小化(c1x1+…cnxn)/(d1x1…dnxn)=cx/dxxi∈{0,1}这里x表示列向量(x1,x2,…,xn)T.0-1值向量的子集Ω称作可行域,而x则是Ω的一个元素,我们称x为可行解。
即可以简化为y=c/d.那么再演变一下:
y-c/d=0.我们目标是求y.那么我们可以假设函数f(y)=y-c/d.
重要结论:
对于分数规划问题,有许多算法都能利用下面的线性目标函数解决问题。
Q(L):
最小化cx-Ldxxi∈{0,1}
记z(L)为Q(L)的最值。
令x*为分数规划的最优解,并且令L*=(cx*)/(dx*)(注:
分数规划的最值)。
那么下面就容易知道了:
z(L)>0当且仅当L z(L)=0当且仅当L=L* z(L)<0当且仅当L>L* 此外,Q(L*)的最优解也能使分数规划最优化。 因此,解决分数规划问题在本质上等同于寻找L=L*使z(L)=0 因此,求解f(y)=0,为其函数的最优解,即可以利用二分的思想逐步推演y,从而求得最优解. 回到题目,我们知道是求解segma(f[V])/segma(E[v])的最大值,同时每个结点对应一个点权,每条边对应一个边权,那么我们就可以联想到应用01分数规划的思想来求解.而01分数规划是与二分紧紧联系在一起的.那么怎么应用二分求解呢? 我们首先想想当仅仅有2个结点环路的时候,问题就演变为f(y)=y-c/d,而y是通过二分逐步推算出来的,那么我们的任务就变为在一定的精度范围内测试求解其最优解.当y-c/d>0时,y减少;y-c/d<0时,y增大.在2个结点之间,那么我们就可用重新将图的权变为y-c/d,这样问题就回到2个结点的环路是否存在负权回路,存在说明y-c/d<0,不存在y-c/d>0.从而进一步推算最优解y。 对于0-1分数规划的Dinkelbach算法的分析 武钢三中吴豪[译] 摘要: 0-1分数规划问题是指求出解集{xi|xi=0或1}使目标(c1x1+c2x2+ +cnxn)/(d1x1+d2x2+…+dnxn)=cx/dx达到最大。 对于分数规划问题,Dinkelbach提出了一个算法,它通过解决一个子问题Q(L)来得到原文题的解。 这里Q是一个线性的最小化目标函数cx-Ldx,且满足x等于0或1。 在本文中,我们证明了Dinkelbach算法在最坏情况下可以在O(log(nM))的时间内解决子问题,这里M=max{max|ci|,max|di|,1}。 1.0-1分数规划问题 要使两个线性函数的比值最大或最小的问题,我们称作分数规划问题或双曲线问题。 分数规划问题在许多领域都可以找到[22]。 它在经济学中的应用有些常见的例子,如寻找最优收入比率或者在效益约束下的最佳物资调配问题。 另外,系统效率也常常用比率来衡量,如收益/时间、利润/风险和消费/时间。 有大量的文章对这类问题做了分析[3,5,12,20,24]。 有几类分数规划问题已被广泛地研究。 如0-1分数规划问题[1],它包含最优比率生成树问题[4],最优比率环问题[8,6,19],分数背包问题[15],以及分数剪枝问题[10]。 在本文中,我们研究0-1分数规划问题,它的描述如下: 令c=(c1,c2,…,cn)和d=(d1,d2,…,dn)为n维整数向量,那么一个0-1分数规划问题用公式描述如下: FP: 最小化 (c1x1+…cnxn)/(d1x1…dnxn)=cx/dx xi∈{0,1} 这里x表示列向量(x1,x2,…,xn)T.0-1值向量的子集Ω称作可行域,而x则是Ω的一个元素,我们称x为可行解。 贯穿全文,我们假定对于任意可行解x,dx都是正数。 这里我们记C=max{max|ci|,1},D=max{max|di|,1}。 那么,显然问题的最优解在区间[-nC,nC]内。 对于分数规划问题,有许多算法都能利用下面的线性目标函数解决问题。 Q(L): 最小化cx-Ldx xi∈{0,1} 记z(L)为Q(L)的最值。 令x*为分数规划的最优解,并且令L*=(cx*)/(dx*)(注: 分数规划的最值)。 那么下面就容易知道了: z(L)>0 当且仅当 L z(L)=0 当且仅当 L=L* z(L)<0 当且仅当 L>L* 此外,Q(L*)的最优解也能使分数规划最优化[7,16,17]。 因此,解决分数规划问题在本质上等同于寻找L=L*使z(L)=0。 出于这个目的,关于L的函数z(L)具有很多不错的性质: 分段线性,凹函数,严格递减,z(-nC)<0,且z(nC)>0。 根据上面的性质,显然当我们确定参量L,我们可以检验最值L*是否大于小于或等于当前的L。 有一些方法能够产生一系列收敛于L*的参量。 其中一种借助于二分搜索[17,21,13]。 在两个不同的可行解的目标值不相同的情况下,他们的差距将大于等于1/(nD)^2。 这暗示我们,当我们采用二分搜索时,最优值L*可以通过解决子问题Q(L)在最多O(log(2nC/(1/nD)^2))<=O(log(nCD))的时间内得到。 在1979年,Megiddo[18]提出了一个巧妙的方法来系统地产生参量序列。 他证明了如果子问题Q(L)能够通过O(p(n))的比较和O(q(n))的累加被解决,那么分数规划问题就能用O(p(n)+q(n))的时间被解决。 另一种方法理论上类似于牛顿迭代法,他被Isbell、Marlow[14]和Dinkelbach[7]提出(也被称作Dinkelbach算法)。 这个算法在[17,21,11]中被讨论(也可能是其他文献)。 下一节将对它进行正式的论述。 Schaible[21]证明了对于非线性分数规划问题,二分搜索的方法的收敛速度仅仅是线性的,而Dinkelbach的收敛速度却是超线性的。 另外,据说Dinkelbach算法在实际应用中强力而有效(参见[13,23]的例子)。 然而,Dinkelbach算法对于0-1分数规划问题的最坏时间复杂度却没有被证明。 在本文中,我们证明了,Dinkelbach算法最多会在O(log(nCD))的时间内解决子问题。 注意它的时间复杂度与普通的二分搜索相同。 我们的结论暗示了,如果对于子问题Q(L)存在多项式算法,Dinkelbach算法也能够在多项式时间内解决分数规划问题。 另外,即使子问题Q(L)是NP-完全或NP-难的,对于特殊的分数规划我们也能够在多项式时间内出解。 2.Dinkelbach算法的论述 它本质上是观察直线 z=cx’-Ldx’ 于函数z(L)在L=L’处相切,这里x’是子问题Q(L’)的最优解。 因此,-dx’是z(L)在L’处的斜率。 而且很容易看出上面的直线与L轴相交与L=cx’/dx’. 现在我们来描述Dinkelbach对于分数规划的算法。 Dinkelbach算法产生了收敛于L*的参量序列,如图1中细线所示的方式。 Dinkelbach算法: 步骤1: 设L=L1,使L*<=L1<=nC 步骤2: 解决子问题Q(L)并得到最优解x 步骤3: 如果z(L)=0,那么输出x并终止。 否则,设L=cx/dx跳到步骤2 为了初始化L1,将用到nC,因此充分挖掘拓展问题的结构将能做出更好的选择。 3.Dinkelbach算法的分析 在这一节中,我们假定Dinkelbach算法终止于第k次。 我们可以得到一个参量序列(L1,L2…Lk)和一个0-1值的向量(x1,x2…xk).z(L)的凸度暗示了下面的不等式: dx1>dx2>…>dxk-1>=dxk>0 cx1+nCdx1>cx2+nCdx2> >cxk-1+nCdxk-1>=cxk+nCxk>=0 由于函数z(L)是严格递减的,也很容易发现 z(L1) >Lk 引理1 如果0>=z(Lr)>-1/nD(2<=r<=k)那么z(Lr)=0 证明由于Lr=cxr-1/dxr-1 z(Lr)=cxr-Lrdxr=cxr-(cxr-1dxr)/(dxr-1)=(cxrdxr-1–cxr-1dxr)/(dxr-1) 假定z(Lr)<0,那么(cxrdxr-1–cxr-1dxr)<=-1。 因此不等式0 它是矛盾的! 上面的引理来源于权向量c和d的完整性。 这个引理暗示了如果z(Lr)>=-1/nD那么z(Lr)=0,因此该算法会中止于第r次。 引理2如果0<=cxr+nCdxr<1,那么z(cxr/dxr)=0 证明由于cxr+nCdxr是整数,如果0<=cxr+nCdxr<1,那么cxr+nCdxr=0并且cxr/dxr=-nC。 由于最值L*>=-nC,xr是分数规划的最优解并且L*=cxr/dxr=-nC。 那么显然有z(cxr/dxr)=z(L*)=0 上面的引理证明了如果cxr+nCdxr<1,那么算法就在r或者r+1次终止。 现在给出主要引理: 引理3 如果1<=r<=k-1那么|z(Lr+1)|<=(1/2)|z(Lr)|或cxr+1+nCdxr+1 <=(1/2)(cxr+nCdxr)将满足。 证明 如果Lr+nC<=0 那么Lr=L*=-nC并且它暗示着z(Lr)b=(1/2)z(Lr+1)=0 现在假定Lr+nC>0。 就出现了两种情况: 情况(i) 首先我们来考虑z(Lr+1)(Lr+nC)<=z(Lr)/2*(Lr+1+nC)。 这个情形如图2所示。 在这个图中,直线z=cxr-Ldxr被记作lr。 这里我们将用到图2的符号。 令M为线段PR的中点。 那么点M的坐标为(Lr+1,z(Lr)(Lr+1+nC)/2/Lr+nC)。 因此条件z(Lr+1)(Lr+nC)<=z(Lr)*(Lr+1+nC)/2暗示着点Q=(Lr+1,z(Lr+1))在线段MR上。 在这个条件下,我们证明不等式cxr+1+nCdxr+1<=(1/2)(cxr+nC,dxr)成立。 这意味着直线lr+1与线段MR相交,lr+1也与线段M’R’相交,这里M’是线段P’R’的中点。 现在我们证明这个不等式: (Lr-Lr+1)(cxr+1+nCdxr+1) =(cxr+1-Lr+1dxr+1)(Lr+nC)-(cxr+1-Lrdxr+1)(Lr+1+nC) =z(Lr+1)(Lr+nC)-(cxr+1-Lrdxr+1)(Lr+1+nC) <=z(Lr)(Lr+1+nC)/2-(cxr-Lrdxr)(Lr+1+nC) =-(1/2)(cxr-Lrdxr)(Lr+1+nC)=-(1/2)(cxr/dxr-Lr)dxr(cxr/dxr+nC) =-(1/2)(Lr+1-Lr)(cxr+nCdxr)=(1/2)(Lr-Lr+1)(cxr+nCdxr) 由于Lr>Lr+1,那么不等式cxr+1+nCdxr+1<=(1/2)(cxr+nCdxr)已经被证明。 情况(ii)接着,考虑z(Lr+1)(Lr+nC)>z(Lr)/2*(Lr+1+nC) |z(Lr+1)|=-z(Lr+1)<-z(Lr)(nC+Lr+1)/2/(nC+Lr) =|z(Lr)|(1-(Lr-Lr+1)/(nC+Lr))/2<=1/2*|z(Lr)| 注意无论|z(L)|还是cx+nCdx在过程中都是不增长的。 在第一次,|z(L)|的值小于等于2n^2*CD。 通过引理1,显然如果存在O(log(2n^2CD/(1/nD)))<=O(log(nCD))次,他们每个都能至少将z(L)减少50%那么,然后就能得到最优解。 同样,引理2暗示了将cx+nCdx减少50%的次数O (log(2n^2CD))<=O(log(nCD))是最坏情况。 引理3证明了每次将|z(L)|或cx+nCdx减少50%。 因此,重复总次数的界限是O(log(nCD))。 定理4 Dinkelbanch算法最坏情况的运行次数是O(log(nCD))<=O(log(nM)),这里M=max{C,D}。 上面的定理证明了Dinkelbanch算法最坏运行次数是O(log(nCD))。 它暗示了,如果对于Q(L)存在强多项式算法,Dinkelbach算法就能在多项式时间内解决分数规划问题。 然而,当我们用多项式算法解决了子问题后,我们需要估计目标函数Q(L)的系数的输入规模。 在下一节,我们将通过分析最优比率生成树和分数调配问题来讨论这一点。 4.讨论 Chandrasekaran[4]提出了最优比率生成树的算法,它是基于二分搜索的。 Dinkelbach算法可以在O(T(v,e)log(vCD))的时间解决该问题,这里v是点的个数,e是边的个数,并且用T(v,e)表示计算普通最小生成树的强多项式算法。 很容易将Chandrasekaran的算法延伸到一般带有分数目标函数的矩阵胚规划问题。 在这种情况下,在这种情形下,函数z(L)的断点数最大为n(n-1)/2(参见[4])因此,当可行域Ω是矩阵胚基础特征向量的集合。 Dinkelbach算法就会在O(min{n^2,log(nCD)})后终止。 对于调配问题,已经研制了许多算法。 大概最有名的算法就是Hungarian方法,并且它在最坏情况下的复杂度是O(v(vlogv+e))[9]。 使用Hungarian方法,Dinkelbach算法可以用O(v(vlogv+e)log(vCD))的时间解决分数调配问题。 在[19]中,Orlin和Ahuja提出了一个O(sqrt(v)e*log(vW))的算法来解决调配问题而且据说他们的算法因为强多项式算法而具有竞争性(参见[2]也可)。 在他们的算法中,它假定边权为整数,并且W代表边权的最大绝对值。 为了将这个算法与Dinkelbach算法相结合,我们需要将在运行第r次解决的的子问题Q(L)用下面式子代替 (dxr-1)cx-(cxr-1)dx 这里xr-1表示代表运行第i次得到的最优解。 因此,在每次运行中,Dinkelbach算法解决边权绝对值小于等于2v^2CD的调配问题。 它暗示了Dinkelbach算法对于调配问题的最坏情况下的时间复杂度为 O(sqrt(v)e(log(2v^3CD))(log(eCD)))<=O(sqrt(v)e(log(vCD))^2) 我们说,如果一个具有线性目标函数的0-1整数规划问题存在多项式算法,我们可以利用上述目标函数在多项式时间内解决它的0-1分数规划问题。 01分数规划(参数搜索)——POJ3621,POJ1639 (2011-04-2901: 51: 19) 转载 标签: 分数规划 参数搜索 杂谈 分类: ACM/ICPC解题报告 01分数规划,又称参数搜索。 即求形如(∑Di*xi)/(∑Ci*xi)的最值问题,其中xi={0,1}即只有取或不取2种状态。 设最值为ans则必有∑(Di-ans*Ci)*xi=0,且因为Di和Ci都是给定的,当xi确定时,等式左边可以看成是一个以ans为变量的单调函数。 因此求最优解转化为求解方程跟的问题。 常见的有(其实就我做过的,很少只有2种): 最优比率生成树,最优比率环。 分别是POJ2728,POJ3621. POJ2728: 给定无向图,给定每条边的权值和耗费,求一棵生成树,使得耗费之和与权值之和的比值最小。 最优比率生成树问题,黑书有给出解法。 据说可以用牛顿迭代的方法,上网查了一下,方法很复杂,就算了-_-||贴个二分的代码。 #include #include #include #include usingnamespacestd; constdoubleINF=100000000; constdoublepre=1e-12; intx[1100],y[1100],z[1100]; doublew[1005][1005],cost[1005][1005],dis[1005][1005],d[1005]; boolvis[1100]; #defineDIS(a,b)sqrt(double(x[a]-x[b])*double(x[a]-x[b])+double(y[a]-y[b])*double(y[a]-y[b])); inlineintaabs(intn) { if(n>0) returnn; return-n; } inlinedoubleprim(intN) { inti,j,t,k; doubleans=0,m; memset(vis,0,sizeof(vis)); for(i=1,d[0]=0;i d[i]=INF; for(i=0;i { for(j=0,m=INF;j vis[j]&&m>d[j])//找最近点 m=d[j],k=j; vis[k]=true;ans+=m; for(j=0;j vis[j]&&d[j]>w[j][k]) d[j]=w[j][k]; } returnans; } intdp01(intn) { inti,j,t; intleft,right,mid; doubletemp; for(i=0;i for(j=i+1;j cost[i][j]=cost[j][i]=aabs(z[i]-z[j]),dis[i][j]=dis[j][i]=DIS(i,j); left=0,right=500000; while(right-left>1) { mid=(left+right)/2; for(i=0;i for(j=i+1;j w[i][j]=w[j][i]=cost[i][j]-dis[i][j]*(mid/10000.0); temp=prim(n); if(temp>0) left=mid; elseright=mid; } returnleft; } intmain() { intN,i; while(scanf("%d",&N),N) { for(i=0;i scanf("%d%d%d",x+i,y+i,z+i); printf("%.3f\n",dp01(N)/10000.0); } } POJ3621: 方法类似,二分枚举答案,SPFA判断可行性。 写这道题的过程中学到了原来SPFA可以用栈写,不过可惜TLE了。 其实SPFA的DFS模式在找负环的时候应该是很快的(存在负环的时候),有空测试一下。 #include #include #include #include #defineINF1000000000 usingnamespacestd; intF[1100],T[5100]; doubledis[1100],w[5050]; boolvis[1100]; intfirst[1100],next[5050],vv[5050]; intcnt[1100]; boolSPFA(intn,doubleans,intm) { intu,v,e,i; memset(cnt,0,sizeof(cnt)); memset(vis,0,sizeof(vis)); for(i=1;i<=n;i++) dis[i]=INF; for(i=1;i<=m;i++) w[i]=ans*T[i]-F[vv[i]]; queue q.push (1);dis[1]=0; while(! q.empty()) { u=q.front();q.pop(); vis[u]=false; e=first[u]; while(e) { v=vv[e]; if(dis[v]>dis[u]+w[e]) { dis[v]=dis[u]+w[e]; if(! vis[v]) { vis[v]=true,q.push(v); cnt[v]++; if(cnt[v]>=n) returntrue; } } e=next[e]; } } returnfalse; } intmain() { intN,M,i,j,u,v; doubleans; scanf("%d%d",&N,&M); for(i=1;i<=N;i++) scanf("%d",F+i); for(i=1;i<=M;i++) { scanf("%d%d%d",&u,&v,&j); next[i]=first[u]; vv[i]=v; T[i]=j; first[u]=i; } doublel=0,r=1000,mid; while (1) { mid=(l+r)/2; if(fabs(l-mid)<1e-6) break; if(SPFA(N,mid,M)) l=mid; elser=mid; } printf("%.2f\n",l); } POJ3621SightseeingCows(01分数规划+spfa) 2011-04-2910: 08 给出一个有向图,问求一个回路,使得回路上的点权之和/边权之和最大。 01分数规划的思想的描述如下: 令c=(c1,c2,…,cn)和d=(d1,d2,…,dn)为n维整数向量,那么一个0-1分数规划问题用公式描述如下: FP: 最小化(c1x1+…cnxn)/(d1x1…dnxn)=cx/dxxi∈{0,1}这里x表示列向量(x1,x2,…,xn)T.0-1值向量的子集Ω称作可行域,而x则是Ω的一个元素,我们称x为可行解。 即可以简化为y=c/d.那么再演变一下: y-c/d=0.我们目标是求y.那么我们可以假设函数f(y)=y-c/d. 重要结论: 对于分数规划问题,有许多算法都能利用下面的线性目标函数解决问题。 Q(L): 最小化cx-Ldxxi∈{0,1} 记z(L)为Q(L)的最值。 令x*为分数规划的最优解,并且令L*=(cx*)/(dx*)(注: 分数规划的最值)。 那么下面就容易知道了: z(L)>0当且仅当L z(L)=0当且仅当L=L* z(L)<0当且仅当L>L* 此外,Q(L*)的最优解也能使分数规划最优化。 因此,解决分数规划问题在本质上等同于寻找L=L*使z(L)=0 因此,求解f(y)=0,为其函数的最优解,即可以利用二分的思想逐步推演y,从而求得最优解. 回到题目,我们知道是求解se
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 01 分数 规划