首页 > 其他分享 >0/1分数规划模型

0/1分数规划模型

时间:2023-01-12 06:33:05浏览次数:59  
标签:分数 dist int double 模型 mid maxn include 规划

0/1分数规划模型

给定n个物品, 每个物品有两个权值ai, bi, 从这n个物品选取k(0 ≤ k ≤ n)个, 使得

\[\frac{\sum_{i=1}^{k}{a_i}}{\sum_{i=1}^{k}{b_i}} \]

最大. 对于该类问题常用二分答案进行求解.

二分答案解决0/1分数规划模型

对于实数mid, 寻找是否有更优解使得

\[\frac{\sum_{i=1}^{k}{a_i}}{\sum_{i=1}^{k}{b_i}} \ge mid \]

对上式进行变形

\[\sum_{i=1}^{k}{a_i} - \sum_{i=1}^{k}{b_i} * mid \ge 0 \]

问题转化为判定是否存在一种选取方案满足上式, 若存在, 说明存在更优解, 令 l = mid, 否则 r = mid.

补充: 0/1分数规划模型涉及到选取方案问题, 常于背包, 贪心, 图论等结合.

例题

POJ2976 Dropping tests (0/1分数规划, 贪心)

思路:这是一道0/1分数规划板子题, 在选取方案时候可以进行贪心, 忽略掉ai/bi较小的k个.

// POJ2976 Dropping tests
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 1005;
int n, k, a[maxn], b[maxn];
double c[maxn];
bool check(double mid) {
    for (int i = 1; i <= n; ++i)
        c[i] = a[i] - b[i] * mid;
    sort(c + 1, c + 1 + n);
    double sum = 0;
    for (int i = k + 1; i <= n; ++i)
        sum += c[i];
    return sum >= 0;
}
int main() {
    while (cin >> n >> k) {
        if (!n && !k)
            break;
        for (int i = 1; i <= n; ++i)
            cin >> a[i];
        for (int i = 1; i <= n; ++i)
            cin >> b[i];
        double l = 0, r = 1;
        while (r - l > 1e-6) {
            double mid = (l + r) / 2;
            if (check(mid))
                l = mid;
            else
                r = mid;
        }
        printf("%.0f\n", l * 100);
    }
    return 0;
}

POJ2728 Desert King

思路: 本题是最小生成树和0/1分数规划的结合.

// POJ2728 Desert King
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
const int maxn = 1005;
int x[maxn], y[maxn], z[maxn], n;
double a[maxn][maxn], b[maxn][maxn];
double dist[maxn];
int vis[maxn];
double get_dist(int u, int v) {
    int dx = abs(x[u] - x[v]);
    int dy = abs(y[u] - y[v]);
    return sqrt(dx * dx + dy * dy);
}
bool check(double mid) {
    // Prim
    memset(dist, 0x7f, sizeof dist);
    memset(vis, 0, sizeof vis);
    dist[1] = 0;
    for (int i = 0; i < n - 1; ++i) {
        int u = -1;
        for (int j = 1; j <= n; ++j)
            if (!vis[j] && (u == -1 || dist[u] > dist[j]))
                u = j;
        vis[u] = 1;
        for (int v = 1; v <= n; ++v)
            if (!vis[v] && dist[v] > a[u][v] - mid * b[u][v])
                dist[v] = a[u][v] - mid * b[u][v];
    }
    double sum = 0;
    for (int i = 2; i <= n; ++i)
        sum += dist[i];
    return sum <= 0;
}
int main() {
    while (scanf("%d", &n) == 1 && n) {
        for (int i = 1; i <= n; ++i)
            scanf("%d%d%d", &x[i], &y[i], &z[i]);
        for (int i = 1; i <= n; ++i)
            for (int j = i; j <= n; ++j) {
                a[i][j] = a[j][i] = abs(z[i] - z[j]);
                b[i][j] = b[j][i] = get_dist(i, j);
            }
        double l = 0, r = 1e9;
        while (r - l > 1e-6) {
            double mid = (l + r) / 2;
            if (check(mid))
                r = mid;
            else
                l = mid;
        }
        printf("%.3f\n", l);
    }
    return 0;
}

P4377[USACO18OPEN] Talent Show G

思路 : 01背包和0/1分数规划的结合. 对n头牛做一遍01背包, 不同的是, 将大于m(m为背包容量, 题目中的W)的部分也统计到f[m]中.

// P4377[USACO18OPEN] Talent Show G
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 255, maxm = 1005;
const double inf = 1e20;
int w[maxn], t[maxn], n, m;
double f[maxm];
bool check(double mid) {
    for (int i = 0; i < maxm; ++i)
        f[i] = -inf;
    f[0] = 0;
    for (int i = 1; i <= n; ++i) {
        for (int j = m; j >= 0; --j) {
            int x = min(j + w[i], m);
            f[x] = max(f[x], f[j] + t[i] - mid * w[i]);
        }
    }
    return f[m] >= 0;
}
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; ++i)
        cin >> w[i] >> t[i];
    double l = 0, r = 1e9;
    for (int i = 1; i <= 100; ++i) {
        double mid = (l + r) / 2;
        if (check(mid))
            l = mid;
        else
            r = mid;
    }
    printf("%d\n", (int)(l * 1000));
    return 0;
}

P3199 [HNOI2009]最小圈

思路:0/1分数规划和判负环结合.本题中的边权对应模型中ai, 边的条数对应bi, 求得是最小值, 只需把 ≥ 改为≤, 问题就转化为判定是否存在负环, 判断负环用spfa的dfs形式快些, 用bfs形式的spfa有些点会T.

// P3199 [HNOI2009]最小圈
#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 3005;
struct Edge {
    int to;
    double w;
    Edge(int _to = 0, double _w = 0) : to(_to), w(_w) {}
};
vector<Edge> e[maxn];
int n, m, cnt[maxn], vis[maxn];
double dist[maxn];
bool dfs(int u, double mid) {
    vis[u] = 1;
    for (int i = 0; i < e[u].size(); ++i) {
        int v = e[u][i].to;
        double w = e[u][i].w;
        if (dist[v] > dist[u] + w - mid) {
            dist[v] = dist[u] + w - mid;
            if (vis[v] || dfs(v, mid))
                return true;
        }
    }
    vis[u] = 0;
    return false;
}
bool spfa(double mid) {
    memset(dist, 0, sizeof dist);
    memset(vis, 0, sizeof vis);
    for (int i = 1; i <= n; ++i)
        if (dfs(i, mid))
            return true;
    return false;
}
int main() {
    cin >> n >> m;
    double l = 0, r = 0;
    while (m--) {
        int u, v;
        double w;
        cin >> u >> v >> w;
        if (w < 0)
            l += w;
        else
            r += w;
        e[u].push_back(Edge(v, w));
    }
    while (r - l > 1e-10) {
        double mid = (l + r) / 2;
        if (spfa(mid))
            r = mid;
        else
            l = mid;
    }
    printf("%.8f\n", l);
    return 0;
}

参考:0/1 分数规划详解

标签:分数,dist,int,double,模型,mid,maxn,include,规划
From: https://www.cnblogs.com/lizsen/p/17045337.html

相关文章

  • 【table master mmocr】Windows下模型训练的配置
    processed_data就是mmocr_pubtabnet_recognition,注意统一命名由图可以看出,那个processed_data就是mmocr_pubtabnet_recognition,而且后面后缀_0927之类的都是日期,可能是......
  • PostGIS之维数扩展的九交模型
    1.概述PostGIS是PostgreSQL数据库一个空间数据库扩展,它添加了对地理对象的支持,允许在SQL中运行空间查询PostGIS官网:AboutPostGIS|PostGISPostGIS官方教程:PostGIS......
  • 数据分享|逻辑回归、随机森林、SVM支持向量机预测心脏病风险数据和模型诊断可视化|附
    原文链接:http://tecdat.cn/?p=24973 最近我们被客户要求撰写关于预测心脏病风险的研究报告,包括一些图形和统计输出。世界卫生组织估计全世界每年有1200万人死于心脏病......
  • R语言如何做马尔可夫转换模型markov switching model|附代码数据
    全文链接:http://tecdat.cn/?p=6962最近我们被客户要求撰写关于马尔可夫转换模型的研究报告,包括一些图形和统计输出。假设有时间序列数据,如下所示。经验表明,目标变量y似......
  • 我的寒假规划(23年)
    写在前面不知不觉已经返乡一个多月了,同时一月已经过半。现在刚刚考完期末考试,临近过年常常需要出去串门,有些东西还没有开始研究。现在现在这里顶一个flag将寒假计划安排出......
  • AIGC 很火,想微调个自己的模型试试看?(不是卖课的)
    去年,我们发布过一篇关于DreamBooth编程马拉松的活动通知,获得了全球社区的广泛关注和参与,中国社区的成员们也对这个活动有非常高的热情。同时我们也收到了后台留言反馈说......
  • laravel的模型删除后动作
    <?phpnamespaceApp\Models;useDcat\Admin\Traits\HasDateTimeFormatter;//useApp\Models\OrderGoods;useIlluminate\Database\Eloquent\Model;classOrderextendsMod......
  • Opencv调用深度学习模型
    2018年04月13日15:19:54 TiRan_Yang 阅读数:1150更多个人分类: TensorFlowPython深度学习 OpenCv从V3.3版本开始支持调用深度学习模型,例如Caffe,Te......
  • 【动态规划】股票买卖问题
    目录股票买卖问题简介应用应用1:Leetcode.121题目分析边界条件状态转移代码实现应用2:Leetcode.122题目分析边界条件状态转移代码实现应用3:Leetcode.123题目分析边界条件状态......
  • 在模型内动态生成按钮
    @api.modeldeffields_view_get(self,view_id=None,view_type='form',toolbar=False,submenu=False):"""Changestheviewdynamically......