两个条件都不太好处理

每行放置的个数实际很小,枚举最多放x

但还是不好放

考虑所有位置先都放上,然后删除最少使得合法

为了凑所有的位置都考虑到,把它当最大流

但是删除最少,所以最小费用

行列相关,左行点,右列点

S到行,流“能填位置”费0

列到T,流“能填位置”费0

i行到i列,流x,即枚举的最大个数

空位(i,j),i行连j列,流1费0

最小费用最大流

意义:流过i行到i列的流量,象征留下一个芯片

流过费用为1的,象征把这个芯片删除。

最大流保证所有位置都考虑到了

最小费用使得最少。

可以发现最后的结果一定满足条件1

条件2?

最大流为flow,费用为cos,总共的位置(多出来的+必填)=sum

放置了tot=sum-cos

如果有x/tot<=A/B那么更新ans=max(ans,tot)
x一定时,tot越大,越可能比A/B小。和最小费用相符。

虽然可能x过大,但是答案一定可以枚举到。

代码:

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){
char ch;x=;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
namespace Miracle{
const int N=;
const int P=;
const int inf=0x3f3f3f3f;
int n,A,B;
struct node{
int nxt,to;
int c,w;
}e[*(N*N+*N)+];
int hd[P],cnt=;
int s,t;
void add(int x,int y,int w,int c){
e[++cnt].nxt=hd[x];
e[cnt].to=y;
e[cnt].c=c;
e[cnt].w=w;hd[x]=cnt; e[++cnt].nxt=hd[y];
e[cnt].to=x;
e[cnt].c=-c;
e[cnt].w=;hd[y]=cnt;
}
int dis[P];
bool in[P];
int incf[P],pre[P];
queue<int>q;
int ans,flow,cos;
int l[N],h[N];
char mp[N][N];
bool spfa(){
memset(dis,inf,sizeof dis);
memset(pre,,sizeof pre);
while(!q.empty()) q.pop();
dis[s]=;
incf[s]=inf;
q.push(s);
while(!q.empty()){
int x=q.front();q.pop();
in[x]=;
for(reg i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
if(e[i].w){
if(dis[y]>dis[x]+e[i].c){
dis[y]=dis[x]+e[i].c;
pre[y]=i;
incf[y]=min(incf[x],e[i].w);
if(!in[y]){
in[y]=;
q.push(y);
}
}
}
}
}
if(dis[t]==inf) return false;
return true;
}
void upda(){
int x=t;
while(pre[x]){
e[pre[x]].w-=incf[t];
e[pre[x]^].w+=incf[t];
x=e[pre[x]^].to;
}
flow+=incf[t];
cos+=dis[t]*incf[t];
}
void EK(int lim){
cos=;flow=;
memset(hd,,sizeof hd);
cnt=;
s=,t=*n+;
for(reg i=;i<=n;++i) {
add(s,i,l[i],);
add(i+n,t,h[i],);
add(i,i+n,lim,);
}
for(reg i=;i<=n;++i){
for(reg j=;j<=n;++j){
if(mp[i][j]=='.') add(i,j+n,,);
}
}
while(spfa()) upda();
}
void clear(){
ans=-;
for(reg i=;i<=n;++i) l[i]=n;
for(reg j=;j<=n;++j) h[j]=n;
}
int main(){
int o=;
while(){
rd(n);rd(A);rd(B);
if(n==&&A==&&B==) break;
++o;
clear();
int can=;
int alr=;
for(reg i=;i<=n;++i){
scanf("%s",mp[i]+);
for(reg j=;j<=n;++j){
if(mp[i][j]=='/') --l[i],--h[j];
else ++can;
if(mp[i][j]=='C') ++alr;
}
}
for(reg x=;x<=n;++x){
EK(x);
int tot=can-cos;
if(flow==can&&A*tot>=x*B) ans=max(ans,tot);
}
ans-=alr;
printf("Case %d: ",o);
if(ans<) printf("impossible");
else printf("%d",ans);
puts("");
}
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
Date: 2019/1/8 10:23:22
*/

最小费用最大流可以考虑两个限制

最大流限制合法

费用流限制优秀

最新文章

  1. 不在折腾---hbase-0.96.2-hadoop2
  2. html5+css 图片自适应
  3. Tomcat安装及配置教程
  4. Android LayoutParams简介
  5. new在c#方法中的使用
  6. cocos2dx 2.x版本:简化提炼tolua++绑定自定义类到lua中使用
  7. 如何让Eclipse的智能提示像VS一样霸气
  8. 【网络流24题】No. 17 运输问题 (费用流)
  9. Android ActionBar详解(二):ActionBar实现Tabs标签以及下拉导航
  10. everything 快速搜索有代价
  11. svn统计代码行数(增量)
  12. APM飞控学习之路的资料
  13. Win32线程安全问题.同步函数
  14. 南大算法设计与分析课程复习笔记(1) L1 - Model of computation
  15. 推箱子 HDU1254 (bfs)
  16. 基于CentOS 7 搭建 GitLab
  17. 【Redis】持久化
  18. Eclipse 下安装 SVN的方法
  19. FLume监控文件夹,将数据发送给Kafka以及HDFS的配置文件详解
  20. cesiumjs学习笔记之三——cesium-navigation插件 【转】

热门文章

  1. youtube视频下载和搬运的方法
  2. Saving James Bond - Easy Version (MOOC)
  3. selenium 图片上传方法。
  4. python编辑用户登入界面
  5. Prometheus+Grafana监控部署实践
  6. Python 日志记录与程序流追踪(基础篇)
  7. 【Python进阶】无论API怎么变,SDK都可以根据URL实现完全动态的调用
  8. Linux虚拟机centos系统安装
  9. mongodb redis memcache 对比
  10. 周总结&lt;1&gt;