题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3232

当然是0/1分数规划。但加的东西和减的东西不在一起,怎么办?

考虑把它们合在一起。因为边围成的形状像一个环,所以把格子的贡献也放到边上,然后正常判环。

放到边上的方法就是:比如竖着的边,可以在每一行上维护该行格子值前缀和,然后指定那个围成的形状是,比如,逆时针的,那么向上的边就加上到它为止的前缀值,向下的边就减去到它为止的前缀值,然后就能判环了!

这样一定只有一个环。但多个环答案不会更优。

还可以用网络流。与 s 相连表示选、与 t 相连表示不选的话,每个点到 s 连该点权值的边,到 t 连边权为0的边,相邻点之间连它们夹着的边权值的边,这样如果相邻的点一个选了一个没选,就得割它们之间的那条边,就能表示了。

自己写了判环的那个。

注意如果以竖着的边算了围住的部分,就不要再用横着的边同时算了!!

请把 eps 设成 1e-7 而不是 1e-5 。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define db double
using namespace std;
const int N=,M=N*N;
const db eps=1e-;
int n,m,fl[N][N]/*,fu[N][N]*/,eh[N][N],el[N][N],cnt[N][N],tot;
db l,r,mid,ans,dis[N][N],w[N][N][];
bool vis[N][N];
queue<pair<int,int> > q;
bool spfa()
{
// printf("mid=%.3lf\n",mid);
while(q.size())q.pop();
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
q.push(make_pair(i,j));
vis[i][j]=; dis[i][j]=; cnt[i][j]=;
if(i)
{
w[i][j][]=fl[i][j]-mid*el[i][j];
// if(mid<3&&mid>2&&el[i][j]==1)
// printf("w[%d][%d][0]=%.3lf\n",i,j,w[i][j][0]);
}
if(j)
{
w[i][j][]=/*-fu[i][j]*/-mid*eh[i][j];
// if(mid<3&&mid>2&&eh[i][j]==1)
// printf("w[%d][%d][1]=%.3lf\n",i,j,w[i][j][1]);
}
if(i<n)
{
w[i][j][]=-fl[i+][j]-mid*el[i+][j];
// if(mid<3&&mid>2&&el[i+1][j]==1)
// printf("w[%d][%d][3]=%.3lf\n",i,j,w[i][j][3]);
}
if(j<m)
{
w[i][j][]=/*fu[i][j+1]*/-mid*eh[i][j+];
// if(mid<3&&mid>2&&eh[i][j+1]==1)
// printf("w[%d][%d][2]=%.3lf\n",i,j,w[i][j][2]);
}
}
while(q.size())
{
int x=q.front().first,y=q.front().second;
q.pop();
vis[x][y]=;
// if(mid>2&&mid<3)printf("x=%d y=%d cnt=%d dis=%.3lf\n",x,y,cnt[x][y],dis[x][y]);
// if(mid>2&&mid<3)printf("fa[%d][%d]=(%d,%d)\n",x,y,fa[x][y][0],fa[x][y][1]);
if(x&&dis[x-][y]<dis[x][y]+w[x][y][])
{
dis[x-][y]=dis[x][y]+w[x][y][];
// printf(" w[%d][%d][0]=%.3lf\n",x,y,w[x][y][0]);
// fa[x-1][y][0]=x; fa[x-1][y][1]=y;
cnt[x-][y]=cnt[x][y]+;
if(cnt[x-][y]==tot)
{
// if(mid>2&&mid<3)
// printf("x-1=%d y=%d dis=%.3lf\n",x-1,y,dis[x-1][y]);
return ;
}
if(!vis[x-][y])
vis[x-][y]=,q.push(make_pair(x-,y));
}
if(y&&dis[x][y-]<dis[x][y]+w[x][y][])
{
dis[x][y-]=dis[x][y]+w[x][y][];
// printf(" w[%d][%d][1]=%.3lf\n",x,y,w[x][y][1]);
// fa[x][y-1][0]=x; fa[x][y-1][1]=y;
cnt[x][y-]=cnt[x][y]+;
if(cnt[x][y-]==tot)
{
// if(mid>2&&mid<3)
// printf("x=%d y-1=%d dis=%.3lf\n",x,y-1,dis[x][y-1]);
return ;
}
if(!vis[x][y-])
vis[x][y-]=,q.push(make_pair(x,y-));
}
if(x<n&&dis[x+][y]<dis[x][y]+w[x][y][])
{
dis[x+][y]=dis[x][y]+w[x][y][];
// printf(" w[%d][%d][3]=%.3lf\n",x,y,w[x][y][3]);
// fa[x+1][y][0]=x; fa[x+1][y][1]=y;
cnt[x+][y]=cnt[x][y]+;
if(cnt[x+][y]==tot)
{
// if(mid>2&&mid<3)
// printf("x+1=%d y=%d dis=%.3lf\n",x+1,y,dis[x+1][y]);
return ;
}
if(!vis[x+][y])
vis[x+][y]=,q.push(make_pair(x+,y));
}
if(y<m&&dis[x][y+]<dis[x][y]+w[x][y][])
{
dis[x][y+]=dis[x][y]+w[x][y][];
// printf(" w[%d][%d][2]=%.3lf\n",x,y,w[x][y][4]);
// fa[x][y+1][0]=x; fa[x][y+1][1]=y;
cnt[x][y+]=cnt[x][y]+;
if(cnt[x][y+]==tot)
{
// if(mid>2&&mid<3)
// printf("x=%d y+1=%d dis=%.3lf\n",x,y+1,dis[x][y+1]);
return ;
}
if(!vis[x][y+])
vis[x][y+]=,q.push(make_pair(x,y+));
}
}
return ;
}
int main()
{
scanf("%d%d",&n,&m); tot=(n+)*(m+);//+1!!!
for(int i=;i<=n;i++)
for(int j=,d;j<=m;j++)
{
scanf("%d",&d); r+=d;
fl[i][j]=fl[i][j-]+d;
// fu[i][j]=fu[i-1][j]+d;
}
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%d",&eh[i][j]);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%d",&el[i][j]);
while(r-l>eps)
{
mid=(l+r)/;
if(spfa()) ans=mid,l=mid+eps;
else r=mid-eps;
}
printf("%.3lf\n",ans);
return ;
}

bzoj 3232 圈地游戏——0/1分数规划(或网络流)的更多相关文章

  1. bzoj3232圈地游戏——0/1分数规划+差分建模+判环

    Description DZY家的后院有一块地,由N行M列的方格组成,格子内种的菜有一定的价值,并且每一条单位长度的格线有一定的费用. DZY喜欢在地里散步.他总是从任意一个格点出发,沿着格线行走直到 ...

  2. bzoj 3232: 圈地游戏

    bzoj 3232: 圈地游戏 01分数规划,就是你要最大化\(\frac{\sum A}{\sum B}\),就二分这个值,\(\frac{\sum A}{\sum B} \geq mid\) \( ...

  3. BZOJ 3232: 圈地游戏 分数规划+判负环

    3232: 圈地游戏 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 966  Solved: 466[Submit][Status][Discuss] ...

  4. bzoj 4753 [Jsoi2016]最佳团体——0/1分数规划

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4753 0/1分数规划裸题. #include<iostream> #includ ...

  5. bzoj 3232: 圈地游戏 01分数规划

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3232 题解: 首先我们看到这道题让我们最优化一个分式. 所以我们应该自然而然地想到01分 ...

  6. bzoj 3232 圈地游戏 —— 01分数规划+最小割建图(最大权闭合子图)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3232 心烦意乱的时候调这道题真是...越调越气,就这样过了一晚上... 今天再认真看看,找出 ...

  7. bzoj 3232: 圈地游戏【分数规划+最小割】

    数组开小导致TTTTTLE-- 是分数规划,设sm为所有格子价值和,二分出mid之后,用最小割来判断,也就是判断sm-dinic()>=0 这个最小割比较像最大权闭合子图,建图是s像所有点连流量 ...

  8. Bzoj1486/洛谷P3199 最小圈(0/1分数规划+spfa)/(动态规划+结论)

    题面 Bzoj 洛谷 题解(0/1分数规划+spfa) 考虑\(0/1\)分数规划,设当前枚举到的答案为\(ans\) 则我们要使(其中\(\forall b_i=1\)) \[ \frac{\sum ...

  9. 【BZOJ3232】圈地游戏(分数规划,网络流)

    [BZOJ3232]圈地游戏(分数规划,网络流) 题面 BZOJ 题解 很神仙的一道题. 首先看到最大化的比值很容易想到分数规划.现在考虑分数规划之后怎么计算贡献. 首先每条边的贡献就变成了\(mid ...

随机推荐

  1. keras----resnet-vgg-xception-inception

    来源: https://www.pyimagesearch.com/2017/03/20/imagenet-vggnet-resnet-inception-xception-keras/ classi ...

  2. jdbcTemplaate queryForObject的两个易混淆的方法

    JdbcTemplate中有两个可能会混淆的queryForObject方法: 1.    Object queryForObject(String sql, Object[] args, Class ...

  3. 【GoldenGate】使用OGG,两个Oracle库之间单向同步数据

    ************************************************************************ ****原文:blog.csdn.net/clark_ ...

  4. Java过滤特殊字符

    Java正则表达式过滤 1.Java过滤特殊字符的正则表达式----转载 java过滤特殊字符的正则表达式[转载] 2010-08-05 11:06 Java过滤特殊字符的正则表达式   关键字: j ...

  5. cesium学习--初识

    一.Cesium 官方介绍:CesiumJS是一个开源的JavaScript库,用于世界级的3D地球仪和地图.任务是为静态和时间动态的内容创建领先的3D地球和地图,具有最好的性能.精度.视觉质量.平台 ...

  6. ios和mac开发 学习资料

    1.WWDC14 Session 409 学习笔记: http://url.cn/Ju2Yt5 2..WWDC14 Session 4092学习笔记: http://url.cn/Rx0mAN 3.i ...

  7. convert from EST/EDT to GMT

    TimeZoneInfo est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"); DateTime ...

  8. c# combobox 绑定枚举方式

    建立一个类 : using System; using System.Collections.Generic; using System.Linq; using System.Text; using ...

  9. 高性能流媒体服务器EasyDSS前端重构(二) webpack + vue + AdminLTE 多页面提取共用文件, 优化编译时间

    本文围绕着实现EasyDSS高性能流媒体服务器的前端框架来展开的,具体EasyDSS的相关信息可在:www.easydss.com 找到! 接上回 <高性能流媒体服务器EasyDSS前端重构(一 ...

  10. git修改commit说明

    当发现说明写错了时,执行git commit --amend,然后修改说明即可.