UVA1104 Chips Challenge
一、题目
有一个 \(n\times n\) 的矩阵,每个元素可能是 .、C、/ 的其中一种,分别表示可以放置芯片、已经放置了芯片、不能放置芯片,你可以分别决定是否可以放置芯片的位置放置芯片。
最后需要满足 \(\forall i\),第 \(i\) 行的芯片个数等于第 \(i\) 列的芯片个数,每一行的芯片个数都不超过总芯片个数的 \(\frac{A}{B}\),问在此情况下能额为放置的芯片个数最大值,如果怎么样都不合法输出 impossible
\(n\leq 40\)
二、解法
如果直接做的话并不好入手,我们考虑调整法,也就是让所有 . 的位置都放芯片再调整。
可以把芯片看成流量,我们可以套路地建出一个二分图。想象第 \(i\) 行的点上具有 \(a_i\) 点流量,第 \(i\) 列的点上具有 \(b_i\) 点流量(分别表示初始状态下它们的芯片个数),那么个数相等的条件可以转化成第 \(i\) 行和第 \(i\) 列同时减少 \(1\) 的流量。
但是最后点上就不能有残余流量,对于 . 的位置我们可以选择不放,设它的位置是 \((i,j)\) 那么它可以让 \(i\) 行 \(j\) 列同时减少 \(1\) 的流量。在此基础上我们还要最大化总芯片数,所以可以考虑增加费用这个意义,我们把同行同列的边费用设置为 \(0\),减少芯片的边费用设置为 \(1\),跑最小费用最大流即可。
还剩下最后一个限制:每一行的芯片个数都不超过总芯片个数A/B,我们可以枚举每一行的芯片个数 \(k\),把同行同列的流量设置为 \(k\),最后可以得到总芯片数 \(sum\),所以我们只需要判断下面两点:满流;\(sum\cdot A\geq k\cdot B\)
三、总结
调整法考虑寻找一个特殊的初始状态,再考虑如何描述增加\(/\)减少的过程。网络流加调整法的应用是常见的,类似的模型还有最小链覆盖,它就是把初始设置有 \(n\) 个链来调整。
网络流是属于图论的,所以它的思维方法中也涉及到思考原问题中的元素怎么对应到图上的每个量上去,比如本题因为要最大化总芯片数我们才考虑增加费用这一维。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int M = 105;
const int inf = 0x3f3f3f3f;
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,A,B,S,T,ans,tot,f[M],a[M],b[M];
int m,dis[M],pre[M],flow[M],lst[M];
struct edge{int v,f,c,next;}e[M*M];char s[M][M];
void add(int u,int v,int F,int c)
{
e[++tot]=edge{v,F,c,f[u]},f[u]=tot;
e[++tot]=edge{u,0,-c,f[v]},f[v]=tot;
}
int bfs()
{
queue<int> q;
for(int i=0;i<=T;i++)
dis[i]=inf,flow[i]=pre[i]=lst[i]=0;
dis[S]=0;flow[S]=inf;q.push(S);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=f[u];i;i=e[i].next)
{
int v=e[i].v,c=e[i].c;
if(dis[v]>dis[u]+c && e[i].f>0)
{
dis[v]=dis[u]+c;
flow[v]=min(flow[u],e[i].f);
pre[v]=u;lst[v]=i;
q.push(v);
}
}
}
return flow[T]>0;
}
void zxy(int k)
{
int res=0,sum=0,all=0;
S=0;T=2*n+1;tot=1;
for(int i=0;i<=T;i++) f[i]=0;
for(int i=1;i<=n;i++)
{
all+=a[i];
add(S,i,a[i],0);
add(i+n,T,b[i],0);
add(i,i+n,k,0);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) if(s[i][j]=='.')
add(i,j+n,1,1);
while(bfs())
{
int t=T;
sum+=flow[t];
res+=flow[t]*dis[t];
while(t)
{
e[lst[t]].f-=flow[T];
e[lst[t]^1].f+=flow[T];
t=pre[t];
}
}
if(sum==all && k*B<=(sum-res)*A)
ans=max(ans,sum-res);
}
void work()
{
m=0;ans=-1;
for(int i=1;i<=n;i++) a[i]=b[i]=0;
for(int i=1;i<=n;i++)
{
scanf("%s",s[i]+1);
for(int j=1;j<=n;j++)
{
m+=(s[i][j]=='C');
a[i]+=(s[i][j]=='C' || s[i][j]=='.');
b[j]+=(s[i][j]=='C' || s[i][j]=='.');
}
}
for(int i=0;i<=n;i++) zxy(i);
if(ans==-1) puts("impossible");
else printf("%d\n",ans-m);
}
signed main()
{
int Case=0;
while(~scanf("%d %d %d",&n,&A,&B) && n+A+B)
{
printf("Case %d: ",++Case);
work();
}
}
UVA1104 Chips Challenge的更多相关文章
- 【题解】uva1104 chips challenge
原题传送门 题目分析 给定一张n*n的芯片. '.'表示该格子可以放一个零件. 'C'表示该格子已经放了一个零件(不能拆下). '/'表示该格子不能放零件. 要求在芯片的现有基础上,放置尽可能多的零件 ...
- [2011WorldFinal]Chips Challenge[流量平衡]
Chips Challenge Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) ...
- UVA1104 芯片难题 Chips Challenge
题目链接 题意 网格上放点,有些强制放,有些不能放,有些可以放可以不放.要求: 第 \(i\) 行的点数 = 第 \(i\) 列的点数 每一行每一列的点数不超过总点数的 \(k\) 倍(\(k\) 已 ...
- 【UVALive - 5131】Chips Challenge(上下界循环费用流)
Description A prominent microprocessor company has enlisted your help to lay out some interchangeabl ...
- 【BZOJ 2673】[Wf2011]Chips Challenge
题目大意: 传送门 $n*n$的棋盘,有一些位置可以放棋子,有一些已经放了棋子,有一些什么都没有,也不能放,要求放置以后满足:第i行和第i列的棋子数相同,同时每行的棋子数占总数比例小于$\frac{A ...
- Bzoj2673 3961: [WF2011]Chips Challenge 费用流
国际惯例题面:如果我们枚举放几个零件的话,第二个限制很容易解决,但是第一个怎么办?(好的,这么建图不可做)考虑我们枚举每行每列最多放几个零件t,然后计算零件总数sum.这样如果可行的话,则有t*B&l ...
- 解题:BZOJ 2673 World Final 2011 Chips Challenge
题面 数据范围看起来很像网络流诶(滚那 因为限制多而且强,数据范围也不大,我们考虑不直接求答案,而是转化为判定问题 可以发现第二个限制相对好满足,我们直接枚举这个限制就可以.具体来说是枚举所有行中的最 ...
- BZOJ2673 [Wf2011]Chips Challenge 费用流 zkw费用流 网络流
https://darkbzoj.cf/problem/2673 有一个芯片,芯片上有N*N(1≤N≤40)个插槽,可以在里面装零件. 有些插槽不能装零件,有些插槽必须装零件,剩下的插槽随意. 要求装 ...
- bzoj3961[WF2011]Chips Challenge
题意 给出一个n*n的网格,有些格子必须染成黑色,有些格子必须染成白色,其他格子可以染成黑色或者白色.要求最后第i行的黑格子数目等于第i列的黑格子数目,且某一行/列的格子数目不能超过格子总数的A/B. ...
随机推荐
- Java基础系列(40)- Arrays类
Arrays类 数据的工具类java.util.Arrays 由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作 查看 ...
- 常用的excel技巧
隐藏 冻结 设置下拉选项 复制.移动sheet 自动求和
- vue 熟悉项目结构 创建第一个自己的组件
* vue开发环境搭建 * 项目入口文件 ./src/main.js // The Vue build version to load with the `import` command // (ru ...
- CI框架 core
https://blog.csdn.net/admin_admin/article/details/51769805 1.扩展控制器 1.在application/core新建一个自己的控制器(MY_ ...
- mysql允许别人通过ip访问本机mysql数据
要想允许别人通过ip访问本机mysql数据库,首先要是本机的mysql允许别的ip访问,也就是授权:其次别人的代码里,要写对本机的ip. 一.本机mysql的授权操作 1.cmd 进入控制台 2.输入 ...
- Python3入门系列之-----看完这一篇文章我终于学会了类
前言 类顾名思义,就是一类事物.或者叫做实例,它用来描述具有共同特征的一类事物.我们在Python中声明类的关键词是class,类还有功能和属性,属性就是这类事物的特征,而功能就是它能做什么,也是就是 ...
- ❤️【Python从入门到精通】(二十六)用Python的PIL库(Pillow)处理图像真的得心应手❤️
您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦. 本篇重点介绍Python处理图像的标准库PIL库,处理图像真的的很方便. 干货满满,建议收藏,需要用到时常看看. 小伙伴们如有问题及需要,欢迎踊跃 ...
- Java实现爬取京东手机数据
Java实现爬取京东手机数据 最近看了某马的Java爬虫视频,看完后自己上手操作了下,基本达到了爬数据的要求,HTML页面源码也刚好复习了下,之前发布两篇关于简单爬虫的文章,也刚好用得上.项目没什么太 ...
- 从一个舒服的姿势插入 HttpClient 拦截器技能点
马甲哥继续写一点大前端,阅读耗时5 minute,行文耗时5 Days 今天我们来了解一下如何拦截axios请求/响应? 这次我们举一反三,用一个最舒适的姿势插入这个技能点. axios是一个基于 p ...
- 修改MySql Root密码(包含忘记密码的方式)
曾几何时,我也是记得MySQL root密码的人,想要修改root密码还不是轻而易举的事?下面前三种修改改方式都是在记得密码的情况下进行修改,如果你忘记了原本的root,请直接跳至 终极 第一种: 在 ...