给出n(n<=1000)个考试的成绩ai和满分bi,要求去掉k个考试成绩,使得剩下的∑ai/∑bi*100最大并输出。

典型的01分数规划

要使∑ai/∑bi最大,不妨设ans=∑ai/∑bi,则∑ai-ans*∑bi=0。

设f[ans]=∑ai-ans*∑bi,我们要求一个ans的最大值,使得存在一组解,满足f[ans]=0,而其他的任意解都有f[ans]<=0(如果f[ans]>0,说明∑ai/∑bi>ans,即还有比ans更优的解),对于∑ai/∑bi,从0~1二分枚举答案,对于每一个枚举到的答案mid,如果f[mid]的最大值>0,则说明存在更大的ans,从mid~r里边进一步找更优的解。否则从l~mid中找。

如何求f[mid]的最大值,f[ans]=∑ai-ans*∑bi=∑(ai-ans*bi)

显然如果mid确定了,那么对于每个考试,ai-mid*bi的值也就确定,那么从大到小排序,取最大的n-m个数进行累加即可。

二分答案法 94MS

 #include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<queue>
#include<string>
#include<sstream>
#define eps 1e-9
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define FOR(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
typedef long long LL;
int i,j,k,n,m,x,y,T,ans,big,cas,a[],b[];
bool flag;
double dp[],d[];
double run(double u)
{
double cur=;
for (int i=;i<=n;i++) d[i]=a[i]-u*b[i];
sort(d+,d++n);
for (i=m+;i<=n;i++) cur+=d[i];
return cur;
} int main()
{
while (scanf("%d%d",&n,&m),n+m)
{
for (i=;i<=n;i++) scanf("%d",&a[i]);
for (i=;i<=n;i++) scanf("%d",&b[i]);
double l=,r=;
while (r-l>eps)
{
double mid=(l+r)/;
if (run(mid)>) l=mid;
else r=mid;
}
printf("%d\n",(int)(r*+0.5));
}
return ;
}

Dinkelbach算法(牛顿迭代法) 32MS

事先随意确定一个数,然后逼近正确答案。

 #include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<queue>
#include<string>
#include<sstream>
#define eps 1e-9
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define FOR(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
typedef long long LL;
struct node
{
double num;
int i;
}d[];
int i,j,k,n,m,x,y,T,big,cas,a[],b[];
bool flag;
double l,ans;
LL p,q;
bool cmp(node a,node b)
{
return a.num<b.num;
}
int main()
{
while (scanf("%d%d",&n,&m),n+m)
{
for (i=;i<=n;i++) scanf("%d",&a[i]);
for (i=;i<=n;i++) scanf("%d",&b[i]);
l=;ans=;
while (fabs(l-ans)>eps)
{
ans=l;
for (i=;i<=n;i++)
{
d[i].num=a[i]*1.0-l*b[i];
d[i].i=i;
}
sort(d+,d++n,cmp);
p=q=;
for (i=m+;i<=n;i++)
{
p+=a[d[i].i];
q+=b[d[i].i];
}
l=p*1.0/q;
}
printf("%d\n",(int)(ans*+0.5));
}
return ;
}

注意Dinkelbach算法中p,q要使用long long

POJ 2976 Dropping tests 01分数规划的更多相关文章

  1. POJ 2976 Dropping tests 01分数规划 模板

    Dropping tests   Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6373   Accepted: 2198 ...

  2. $POJ$2976 $Dropping\ tests$ 01分数规划+贪心

    正解:01分数规划 解题报告: 传送门! 板子题鸭,,, 显然考虑变成$a[i]-mid\cdot b[i]$,显然无脑贪心下得选出最大的$k$个然后判断是否大于0就好(,,,这么弱智真的算贪心嘛$T ...

  3. POJ - 2976 Dropping tests(01分数规划---二分(最大化平均值))

    题意:有n组ai和bi,要求去掉k组,使下式值最大. 分析: 1.此题是典型的01分数规划. 01分数规划:给定两个数组,a[i]表示选取i的可以得到的价值,b[i]表示选取i的代价.x[i]=1代表 ...

  4. POJ 2976 Dropping tests(分数规划)

    http://poj.org/problem?id=2976 题意: 给出ai和bi,ai和bi是一一配对的,现在可以删除k对,使得的值最大. 思路: 分数规划题,可以参考<挑战程序竞赛> ...

  5. [poj 2976] Dropping tests (分数规划 二分)

    原题: 传送门 题意: 给出n个a和b,让选出n-k个使得(sigma a[i])/(sigma b[i])最大 直接用分数规划.. code: //By Menteur_Hxy #include & ...

  6. Dropping tests(01分数规划)

    Dropping tests Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8176   Accepted: 2862 De ...

  7. [poj2976]Dropping tests(01分数规划,转化为二分解决或Dinkelbach算法)

    题意:有n场考试,给出每场答对的题数a和这场一共有几道题b,求去掉k场考试后,公式.的最大值 解题关键:01分数规划,double类型二分的写法(poj崩溃,未提交) 或者r-l<=1e-3(右 ...

  8. POJ2976 Dropping tests —— 01分数规划 二分法

    题目链接:http://poj.org/problem?id=2976 Dropping tests Time Limit: 1000MS   Memory Limit: 65536K Total S ...

  9. poj Dropping tests 01分数规划---Dinkelbach算法

    果然比二分要快将近一倍.63MS.二分94MS. #include <iostream> #include <algorithm> #include <cstdio> ...

随机推荐

  1. 跟我学android-使用Eclipse开发第一个Android应用(三)

    打开Eclipse,选择 File—New –Android Application Project Application Name  就是我们的 应用名称,也是我们在手机应用程序列表里看到的名称. ...

  2. ch01.深入理解C#委托及原理(转)

    ch01..深入理解C#委托及原理_<没有控件的ASPDONET> 一.委托 设想,如果我们写了一个厨师做菜方法用来做菜,里面有 拿菜.切菜.配菜.炒菜 四个环节,但编写此方法代码的人想让 ...

  3. jQuery中$.get()、$.post()和$.ajax()

    jQuery.get()方法: $.get(url,data,success(response,status,xhr),dataType) 该函数是简写的 Ajax 函数,等价于: $.ajax({ ...

  4. C++ STL基本容器的使用

    C++中有两种类型的容器:顺序容器和关联容器.顺序容器主要有vector.list.deque等.其中vector表示一段连续的内存,基于数组实现,list表示非连续的内存,基于链表实现,deque与 ...

  5. winform 绘制label 中文字 - 摘

    private void label2_Paint(object sender, PaintEventArgs e) {//绘制label中文字 string text = "Sri Lan ...

  6. 一个md5加密的工具类,用的虚拟机的包,不需要额外导包

    package com.yun.park.service.utils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import jav ...

  7. sql中关于case when的一个例子

    SELECT rownum R, a.expert_id as USERID, a.expert_id as TYPE, b.type_desc as TYPE_DESC, a.sex as SEX, ...

  8. codevs4373 窗口

    题目描述 Description 给你一个长度为N的数组,一个长为K的滑动的窗体从最左移至最右端,你只能见到窗口的K个数,每次窗体向右移动一位,如下表: Window position Min val ...

  9. Shortest Prefixes

    poj2001:http://poj.org/problem?id=2001 题意:给你一些单词,然后让你寻找每个单词的一个前缀,这个前缀能够唯一表示这个单词,并且是最短的. 题解:直接用trie树来 ...

  10. SPRING-MVC访问静态文件,如jpg,js,css

    如何你的DispatcherServlet拦截 *.do这样的URL,就不存在访问不到静态资源的问题.如果你的DispatcherServlet拦截“/”,拦截了所有的请求,同时对*.js,*.jpg ...