01分数规划

背景:根据楼教主回忆,曾经在一场比赛中秒掉了一道最优比例生成树问题,导致很多人跟风失败,最终悲剧。

  • 什么是01分数规划呢?

这样的等式求最大,最小即为01分数规划。  

如果你不知道该如何去解,你可能会去贪心,DP去做,但是这样是很复杂的。

  • 解法:二分,迭代(计算几何大佬都知道这种方案,但是我不是)

  • 直接二分ans,​ ​ ​ 根据符号二分转移。

例题一:pku 2796

题意: 最大。

#include <stdio.h>
#include <algorithm>

using namespace std;

const int maxn = ;

int n,k;
double a[maxn],b[maxn];
double c[maxn];

bool cmp(double a,double b) {
return a > b;
}

bool calc(double x) {
for(int i = ; i < n; i++)
c[i] = a[i] - x*b[i];
sort(c,c+n,cmp);

double sum = ;
for(int i = ; i < n-k; i++)
sum +=c[i];
if(sum>=) return true;
return false;

}

int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d%d",&n,&k),n) {

for(int i = ; i < n; i++) scanf("%lf",&a[i]);
for(int i = ; i < n; i++) scanf("%lf",&b[i]);

double l = ,r = ;

while(r-l>1e-) {
double mid = (l + r)/;

if(calc(mid))
l = mid;
else r = mid;

}
printf("%.0lf\n",l*);

}
return ;
}

例题二:pku 2728 最优比例生成树

题意:给定n 个点,坐标(x,y,z),n条无向边的图,国王将这n个点连起来(生成树),建一条边有花费, 求单位最小花费最小比例。

同理:二分这个比例,边权为 ,最小生成树 ans >= 0,说明 x过小,二分转移 l = mid;

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = ;

double maps[maxn][maxn];
bool vis[maxn];
double dis[maxn];

int n;

double Prim() {
memset(vis,false,sizeof(vis));
for(int i = ; i<= n; i++)
dis[i] = ;

double ans = ;
dis[] = ;

for(int i = ; i <= n; i++) {
double tmp = ;
int k = ;

for(int j = ; j <= n; j++) {
if(!vis[j]&&dis[j]<tmp) {
tmp = dis[j];
k = j;
}
}

vis[k] = true;
ans += tmp;

for(int j = ; j<= n; j++) {
if(!vis[j]&&dis[j]>maps[k][j])
dis[j] = maps[k][j];
}

}
return ans;
}

struct Node {
double x,y,z;
}nodes[maxn];

double dist(int i,int j,double x) {
double fx = fabs(nodes[i].x-nodes[j].x);
double fy = fabs(nodes[i].y-nodes[j].y);
double fz = fabs(nodes[i].z-nodes[j].z);
return fz - x*sqrt(fx*fx+fy*fy);
}

double eps = 1e-;

int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d",&n),n) {

for(int i = ; i <= n; i++) scanf("%lf%lf%lf",&nodes[i].x,&nodes[i].y,&nodes[i].z);

double l = ,r = ;

while(r-l>1e-) {
double mid = (r+l)/;

for(int i = ; i <= n; i++)
for(int j = ; j <= n; j++)
maps[i][j] = dist(i,j,mid);

double ans = Prim();

if(ans<=)
r = mid;
else l = mid;
}

printf("%.3f\n",l);
}

return ;
}

例题三:pku 3621 最优比例环。(双倍经验题Uva 11090,题意相反)

题意:给定一个L个节点,P条有向边的图,奶牛从一个城市出发,走一个环回到起点,点上有权值,边上也有长度,求单位长度的点权最大。

分析:还是二分 ans,由于是一个环,一条边上,算起点权值就好了。改边权, ,

由于求的是比例最大,这时SPFA,应反向松弛,才能得到最大的比例。

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <string.h>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = ;

struct Edge {
int from,to;
double dist;
};

struct BellmanFord
{
int n, m;
vector<Edge> edges;
vector<int> G[maxn];
bool inq[maxn];
double d[maxn];
int p[maxn];
int cnt[maxn];

void init(int n)
{
this->n = n;
for(int i = ; i < n; i++) G[i].clear();
edges.clear();
}

void AddEdge(int from, int to, double dist)
{
edges.push_back((Edge)
{
from, to, dist
});
m = edges.size();
G[from].push_back(m-);
}

bool negativeCycle()
{
queue<int> Q;
memset(inq, , sizeof(inq));
memset(cnt, , sizeof(cnt));
for(int i = ; i < n; i++)
{
d[i] = ;
inq[] = true;
Q.push(i);
}

while(!Q.empty())
{
int u = Q.front();
Q.pop();
inq[u] = false;
for(int i = ; i < (int)G[u].size(); i++)
{
Edge& e = edges[G[u][i]];
if(d[e.to] < d[u] + e.dist) //反向松弛
{
d[e.to] = d[u] + e.dist;
p[e.to] = G[u][i];
if(!inq[e.to])
{
Q.push(e.to);
inq[e.to] = true;
if(++cnt[e.to] > n) return true;
}
}
}
}
return false;
}
}sol;
int L,P;
double f[maxn];
double t[maxn];

vector<Edge> edgestmp;

int main()
{
//freopen("in.txt","r",stdin);
scanf("%d%d",&L,&P);

sol.init(L);
for(int i = ; i < L; i++) scanf("%lf",&f[i]);
for(int i = ; i < P; i++) {
int u,v;
double dist;
scanf("%d%d%lf",&u,&v,&dist);
u--;v--;
edgestmp.push_back((Edge){u,v,dist});
sol.AddEdge(u,v,dist);
}

double l = ,r = ;
while(r-l>1e-) {
double mid = (r+l)/;

sol.init(L);

for(int i = ; i < P; i++) {
int u = edgestmp[i].from;
int v = edgestmp[i].to;
double dist = edgestmp[i].dist;
sol.AddEdge(u,v,f[u]-mid*dist);
}

if(sol.negativeCycle())
l = mid;
else r = mid;
}

printf("%.2f\n",l);
return ;
}
												

ACM-ICPC (10/12)的更多相关文章

  1. 2016 ACM/ICPC Asia Regional Qingdao Online 1001/HDU5878 打表二分

    I Count Two Three Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  2. Java in ACM/ICPC

    目录 Java在ACM/ICPC中的特点 在ACM/ICPC中使用Java需要注意的问题 Java与高精度计算 1.Java在ACM/ICPC中的特点 Java的语法和C++几乎相同 Java在执行计 ...

  3. 2016 ACM/ICPC Asia Regional Qingdao Online(2016ACM青岛网络赛部分题解)

    2016 ACM/ICPC Asia Regional Qingdao Online(部分题解) 5878---I Count Two Three http://acm.hdu.edu.cn/show ...

  4. 2017 ACM/ICPC Asia Regional Qingdao Online

    Apple Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submi ...

  5. ACM/ICPC 之 BFS(离线)+康拓展开(TSH OJ-玩具(Toy))

    祝大家新年快乐,相信在新的一年里一定有我们自己的梦! 这是一个简化的魔板问题,只需输出步骤即可. 玩具(Toy) 描述 ZC神最擅长逻辑推理,一日,他给大家讲述起自己儿时的数字玩具. 该玩具酷似魔方, ...

  6. ACM ICPC 2015 Moscow Subregional Russia, Moscow, Dolgoprudny, October, 18, 2015 D. Delay Time

    Problem D. Delay Time Input file: standard input Output file: standard output Time limit: 1 second M ...

  7. 【转】ACM/ICPC生涯总结暨退役宣言—alpc55

    转自:http://hi.baidu.com/accplaystation/item/ca4c2ec565fa0b7fced4f811 ACM/ICPC生涯总结暨退役宣言—alpc55 前言 早就该写 ...

  8. hduoj 4715 Difference Between Primes 2013 ACM/ICPC Asia Regional Online —— Warmup

    http://acm.hdu.edu.cn/showproblem.php?pid=4715 Difference Between Primes Time Limit: 2000/1000 MS (J ...

  9. hduoj 4712 Hamming Distance 2013 ACM/ICPC Asia Regional Online —— Warmup

    http://acm.hdu.edu.cn/showproblem.php?pid=4712 Hamming Distance Time Limit: 6000/3000 MS (Java/Other ...

  10. hduoj 4707 Pet 2013 ACM/ICPC Asia Regional Online —— Warmup

    http://acm.hdu.edu.cn/showproblem.php?pid=4707 Pet Time Limit: 4000/2000 MS (Java/Others)    Memory ...

随机推荐

  1. java se系列(二) 关键字、注释、常量、进制转换、变量、数据类型转换、运算符

    1 关键字 1.1 关键字的概述 Java的关键字对java的编译器有特殊的意义,他们用来表示一种数据类型,或者表示程序的结构等,关键字不能用作变量名.方法名.类名.包名. 1.2 常见的关键字 备注 ...

  2. AppInventor2笔记

    将视觉化的 块语言 翻译为 Android上的实现 的编译器使用了Kawa语言框架,而Kawa是Scheme编程语言的方言,由Per Bothner开发,并由自由软件基金会发布,它是GNU操作系统的一 ...

  3. oracle 备份恢复篇(一)---rman

    一,rman介绍 RMAN(Recovery Manager)是随Oracle服务器软件一同安装的工具软件,它可以用来备份和恢复数据库文件.归档日志和控制文件,用来执行完全或不完全的数据库恢复.与传统 ...

  4. 理解 glibc malloc:主流用户态内存分配器实现原理

    https://blog.csdn.net/maokelong95/article/details/51989081 Understanding glibc malloc 修订日志: 2017-03- ...

  5. Git学习手记

    直接使用github的客户端即可 1.简介 集中化的版本控制系统( Centralized Version Control Systems,简称 CVCS )应运而生.这类系统,诸如 CVS,Subv ...

  6. TOJ 2641 Gene

    描述 How can millions of different and complex structures be built using only a few simple building bl ...

  7. 记一次MongoDB性能问题

    下面文章转载自火丁笔记,原作者描述了一次MongoDB数据迁移过程中遇到的性能问题及其解决方案,中间追查问题的方法和工具值得我们学习.下面是其原文: 最近忙着把一个项目从MySQL迁移到MongoDB ...

  8. VS2015自定义类模板的方法

    在前一段时间忽然想给自己电脑上的vs新建类的时候添加一个自定义个注释,但是在网上搜了很久都是说vs2012之类的方法系统也都是win7.XP之类的独独没有win8的.故此自己不断的尝试修改发现方法如下 ...

  9. iframe中插入代码并执行

    最近有需求通过iframe插入代码.有蛮多方法,如下: 1 var iframe = document.getElementById('previewUrl'); 2 iframe.src = 'ab ...

  10. String字符串操作

    char chars[] ={'a','b','c'}; String s = new String(chars); int len = s.length();//字符串长度 System.out.p ...