【定义】
01分数规划问题:所谓的01分数规划问题就是指这样的一类问题,给定两个数组,a[i]表示选取i的收益,b[i]表示选取i的代价。如果选取i,定义x[i]=1否则x[i]=0。每一个物品只有选或者不选两种方案,求一个选择方案使得R=sigma(a[i]*x[i])/sigma(b[i]*x[i])取得最值,即所有选择物品的总收益/总代价的值最大或是最小。
(这一段是我网络上考的。- =)
解决方案
R=sigma(a[i]*x[i])/sigma(b[i]*x[i])
sigma(a[i]*x[i])/sigma(b[i]*x[i])>=R
sigma(a[i]*x[i])*R-sigma(b[i]*x[i])>=0
求出R 即使答案。
首先解决这种问题的方法,一般有两种 二分 以及 迭代 。
而如何检验 是否可以是答案,只要 求出 c[i]=(a[i]*x[i])*R-(b[i]*x[i]) 进行排序 尽量取大的 即可。
(当我见到这种题型的时候 第一反应是 贪心算法 - - 根据比值排 结果...... 貌似是我太逗了~~~~!! 后来举了一个反例 我知道了 INF/INF 10/1 1/2 虽然第一个的比值比三个好 但是 - -)
poj 2976
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <string.h>
using namespace std;
#define maxn 1010
double a[maxn],b[maxn],c[maxn];
int n,m;
bool judge(double x)
{
double sum=0;
for(int i=0;i<n;i++)
c[i]=a[i]-b[i]*x;
sort(c,c+n);
for(int i=0;i<m;i++)
sum+=c[n-i-1];
return sum>0;
}
int main()
{
while(scanf("%d%d",&n,&m)&&n+m)
{
m=n-m;
double l=0,r=100,mid,ret;
for(int i=0;i<n;i++)
{
scanf("%lf",&a[i]);
a[i]*=100;
}
for(int i=0;i<n;i++)
{
scanf("%lf",&b[i]);
}
while(fabs(r-l)>=0.001)
{
mid=(r+l)/2;
if(judge(mid))
{
l=mid;
}
else
{
r=mid;
}
}
printf("%.0lf\n",mid);
}
return 0;
}