POJ 2976--Dropping tests(Dinkelbach求0/1规划)
来源:互联网 发布:excel怎么汇总数据 编辑:程序博客网 时间:2024/06/03 23:14
题意:类似于GPA求解的过程,给定两个规模为N的数组A,B,其中A的数小于等于相同位置上B的数,请选择k个位置,使A中数的和除以B中数的和达到最大。
题解:类似于背包,每个位置有0,1两种选择。
- 设N维列向量X,其中只包含0,1两种元素。则A*X就等于分子的和,B*X就相等于与分母的和。
- 设相除的结果为L,即L = (A*X)/(B*X)。
- 我们设一关于L的函数,Z = A*X-(B*X)*L,其中X只含有k个1,且在给定L的情况下使Z值最大,可以通过排序求得Z值(易知X向量是可能随L变化的)。注意Z是一个关于L的分段线性的凹函数。
一、二分法
- 二分法的一般步骤就是首先给出所求值的大致范围,然后根据单调性逐渐缩小这个范围达到所需的精度。
- 设最大的比值为L_max,即A*X <= (B*X)*L_max,当且仅当X为最优的选取时取得等号,Z(L_max) = 0。
- 若L > L_max,有A*X <= (B*X)*L_max < (B*X)*L,所以Z(L) < 0。
- 若L < L_max,当X为与L_max对应的最优选取时,易知Z(L) > 0。
二、Dinkelbach算法
- 类似于牛顿迭代法求方程的解,设一方程f(x) = 0,在区间[a,b]内,f'(x),f''(x)保号。则我们设x[0] = a或者b,x[k+1]= x[k]-f(x[k])/f'(x[k]),左边的迭代方程就是求的过点(x[k],f(x[k]))切线与x轴的交点的横坐标,画个图就知道这个交点的x[k+1]处于曲线与x轴交点x*(方程的解)与x[k]之间。
- 同样,我们也是求Z(L) = 0的值,虽然X可能随着L变化,但是易知这种变化是很缓慢的,我们可以近似地认为Z(L)在L[k]处的切线斜率为-B*X,则有L[k+1] = L[k]-Z(L)/(-B*X) =(A*X)/(B*X)。
二分法:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define eps (1e-3)#define INF 0X7FFFFFFFclass solve{private: int N,k; int min_a,max_b; int scores[2][1005];public: solve(int x,int y):N(x),k(y) { processIn(); printf("%d\n",two_partition()); } int processIn(); int two_partition();};int solve::two_partition(){ double left,right,mid; double tmpDiff[1005]; double sum; left = ((double)min_a)*100.0/((double)max_b); right = 100; while(right-left > eps) { sum = 0; mid = (right+left)/2.0; for(int i = 0;i < N;i++) { tmpDiff[i] = scores[0][i]*100.0-mid*scores[1][i]; } sort(tmpDiff,tmpDiff+N); for(int i = 0;i < N-k;i++) { sum += tmpDiff[N-1-i]; } if(sum > 0) { left = mid; } else { right = mid; } } return (int)(left+0.5);}int solve::processIn(){ min_a = INF; max_b = -1; for(int i = 0;i < N;i++) { scanf("%d",scores[0]+i); min_a = min(min_a,scores[0][i]); } for(int i = 0;i < N;i++) { scanf("%d",scores[1]+i); max_b = max(max_b,scores[1][i]); } return 0;}int main(){ int n,k; while(~scanf("%d%d",&n,&k)&&n) { solve Dropping_tests(n,k); } return 0;}
Dinkelbach:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;#define eps (1e-3)#define INF 0X7FFFFFFF#define maxN 1005struct node{ double unitL; int index; friend bool operator< (node x,node y) { return x.unitL > y.unitL; }}L_array[maxN];class solve{private: int N,k; int scores[2][maxN];public: solve(int x,int y):N(x),k(y) { processIn(); printf("%d\n",dinkelbach()); } int processIn(); int dinkelbach();};int solve::dinkelbach(){ double pre_L,L; double sum_a,sum_b; pre_L = 0; L = 50; sum_a = 0.5; sum_b = 1; while(fabs(pre_L-L) > eps) { sum_a = sum_b = 0; for(int i = 0;i < N;i++) { L_array[i].index = i; L_array[i].unitL = (double)scores[0][i]*100.0-L*(double)scores[1][i]; } sort(L_array,L_array+N); for(int i = 0;i < N-k;i++) { sum_a += (double)scores[0][L_array[i].index]*100.0; sum_b += (double)scores[1][L_array[i].index]; } pre_L = L; L = sum_a/sum_b; } return (int)(L+0.5);}int solve::processIn(){ for(int i = 0;i < N;i++) { scanf("%d",scores[0]+i); } for(int i = 0;i < N;i++) { scanf("%d",scores[1]+i); } return 0;}int main(){ int n,k; while(~scanf("%d%d",&n,&k)&&n) { solve Dropping_tests(n,k); } return 0;}
0 0
- POJ 2976--Dropping tests(Dinkelbach求0/1规划)
- poj 2976: Dropping tests(01分数规划--Dinkelbach算法)
- POJ 2976 Dropping tests 01分数规划Dinkelbach算法
- POJ 2976 Dropping tests 01分数规划 模板 二分&&Dinkelbach
- poj Dropping tests 01分数规划---Dinkelbach算法
- poj Dropping tests 01分数规划---Dinkelbach算法
- POJ 2976-Dropping tests(01分数规划_二分||Dinkelbach算法)
- [POJ 2976]Dropping tests(0-1分数规划)
- poj 2976 Dropping tests 【0-1分数规划】
- POJ 2976 Dropping tests 01分数规划
- POJ 2976 Dropping tests 01分数规划
- poj-2976-Dropping tests-01分数规划
- POJ 2976 Dropping tests 01分数规划
- 【POJ】2976 Dropping tests 01分数规划
- [poj 2976]Dropping tests 01分数规划
- POJ 2976 Dropping tests & 分数规划讲解
- POJ 2976 Dropping tests (01分数规划)
- POJ 2976 Dropping tests(01分数规划)
- JavaScript Tween算法及缓动效果
- java中WeakHashMap的个人理解
- 编程珠玑里的日期函数
- 更改Oracle10g服务端字符集
- JavaScript之七:DOM
- POJ 2976--Dropping tests(Dinkelbach求0/1规划)
- 使用Genymotion调试出现错误INSTALL_FAILED_CPU_ABI_INCOMPATIBLE解决办法
- POJ 1149 PIGS EK最大流
- 4SUM
- Where should we fork this repository?
- Android GPS 流程笔记
- SPOJ 220. Relevant Phrases of Annihilation(后缀数组多次不重叠子串)
- STL之list/vector/deque
- JVM监控工具-Jvisualvm