POJ 2976 Dropping tests (01分数规划)

原题地址:http://poj.org/problem?id=2976
题意:n种数,每种数有2个属性,a,b ,选出n-k种数,最大化∑A(n-k)/∑B(n-k)
思路:简单的01分数规划.
觉得大佬的博客讲的很好
http://www.cnblogs.com/TheRoadToTheGold/p/6546981.html

关于分数规划的讲解
https://blog.csdn.net/ruoruo_cheng/article/details/52540565
https://www.jianshu.com/p/4bc6037fe8e1
https://blog.csdn.net/hhaile/article/details/8883652

https://blog.csdn.net/hzoi_ztx/article/details/54898323
二分法

#include <cmath>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <set>
#include <cctype>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define MOD 1e9+7
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define CLR(x,y) memset((x),y,sizeof(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e5 + 5;
int n, k;
int a[maxn], b[maxn];
double  d[maxn];
int  check(double L) {
    double sum = 0;
    for(int i = 1; i <= n; i++) d[i] = (double)a[i] - L * b[i];
    sort(d + 1, d + 1 + n);
    for(int i = n; i >= n - k + 1; i--) sum += d[i];
    if(sum > 0) return 1;
    else return 0;
}
int main() {
    while(~scanf("%d%d", &n, &k), n + k) {
        //double mx = 0;
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }
        k = n - k;
        for(int i = 1; i <= n; i++) {
            scanf("%d", &b[i]);
            //mx = max(mx, 1.0 * a[i] / b[i]);//也可以
        }
        double l = 0;
        double r = INF;
        for(int i=1;i<=100;i++) {
            double mid = (l + r) / 2;
            if(check(mid))  l = mid;
            else r = mid;
        }
        printf("%.0f\n", r * 100);
    }
    return 0;
}

迭代法

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
const int maxn = 1e3+10;
using namespace std;
int n,k;
struct node{
    int a,b;
}val[maxn];
double p;
int cmp(node x, node y){
    return x.a - (p * x.b) > y.a - (p * y.b);
}
double check(double mid){
    p = mid;
    sort(val, val + n, cmp);
    double total_a = 0,total_b = 0;
    for(int i = 0; i < n - k; i++){
        total_a += val[i].a;
        total_b += val[i].b;
    }
    return (total_a/total_b);
}
int main(){
    while(~scanf("%d%d",&n,&k) && n){
        for(int i = 0; i < n; i++){
            scanf("%d",&val[i].a);
        }
        for(int i = 0; i < n; i++){
            scanf("%d",&val[i].b);
        }
        double l = 0, r;
        for(int i = 0; i < 10; i++){
            r = check(l);
            l = r;
        }
        printf("%d\n",(int)round(l*100));
    }
    return 0;
}

杂记:


这里写图片描述

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/81320014