[SRM577]BoardPainting
题意:一个全白的网格,你要将一些格子涂黑,每次只能选一行或一列中的连续白格涂黑,问最小操作次数
先假装我们一次涂一个联通块,那么答案就是联通块个数,然后在这个基础上增加一些代价让方案变得合法
考虑这样建图:对两个水平相邻的要涂黑的格子$x,y$,建新点$u$,连$(S,u,1),(u,x,\infty),(u,y,\infty)$,对两个竖直相邻的要涂黑的格子$x,y$,建新点$v$,连$(x,v,\infty),(y,v,\infty),(v,T,1)$
如果存在一条$S\rightarrow u\rightarrow x\rightarrow v\rightarrow T$的路径,说明当前的涂色方案并不合法(染色转弯),于是我们需要把这条路径割掉,代表从联通块中分出一部分让答案变得合法,所以答案还要加上这个图的最小割
#include<stdio.h> #include<string.h> #include<algorithm> #include<vector> #include<string> using namespace std; const int inf=2147483647; int h[7510],nex[40010],to[40010],cap[40010],M=1,S,T; void ins(int a,int b,int c){ M++; to[M]=b; cap[M]=c; nex[M]=h[a]; h[a]=M; } void add(int a,int b,int c){ ins(a,b,c); ins(b,a,0); } int dis[7510],q[7510]; bool bfs(){ int head,tail,x,i; memset(dis,-1,sizeof(dis)); head=tail=1; q[1]=S; dis[S]=0; while(head<=tail){ x=q[head++]; for(i=h[x];i;i=nex[i]){ if(cap[i]&&dis[to[i]]==-1){ dis[to[i]]=dis[x]+1; if(to[i]==T)return 1; q[++tail]=to[i]; } } } return 0; } int cur[7510]; int dfs(int x,int flow){ if(x==T)return flow; int us=0,i,t; for(i=cur[x];i&&flow;i=nex[i]){ if(cap[i]&&dis[to[i]]==dis[x]+1){ t=dfs(to[i],min(flow,cap[i])); cap[i]-=t; cap[i^1]+=t; us+=t; flow-=t; if(cap[i])cur[x]=i; } } if(us==0)dis[x]=-1; return us; } int dicnic(){ int ans=0; while(bfs()){ memcpy(cur,h,sizeof(h)); ans+=dfs(S,inf); } return ans; } int id[60][60]; class BoardPainting{ public: int minimalSteps(vector<string>mp){ int n,m,i,j,N,ans; n=mp.size(); m=mp[0].length(); N=2; S=1; T=2; ans=0; for(i=0;i<n;i++){ for(j=0;j<m;j++){ if(mp[i][j]=='#'){ id[i][j]=++N; ans++; } } } for(i=0;i<n;i++){ for(j=0;j<m;j++){ if(id[i][j]){ if(id[i+1][j]){ ans--; N++; add(id[i][j],N,inf); add(id[i+1][j],N,inf); add(N,T,1); } if(id[i][j+1]){ ans--; N++; add(S,N,1); add(N,id[i][j],inf); add(N,id[i][j+1],inf); } } } } return ans+dicnic(); } }; /* int main(){ BoardPainting cl; vector<string>v; char s[110]; for(scanf("%s",s);s[0]!='E';scanf("%s",s))v.push_back(s); printf("%d",cl.minimalSteps(v)); } */
[SRM577]BoardPainting的更多相关文章
- Topcoder口胡记 SRM 562 Div 1 ~ SRM 599 Div 1
据说做TC题有助于提高知识水平? :) 传送门:https://284914869.github.io/AEoj/index.html 转载请注明链接:http://www.cnblogs.com/B ...
随机推荐
- Linux分区设置
基本3个就可以了 序号 路径 大小 格式 ① /boot 200MB ext4 ② 物理内存*1-1.5 swap ③ / 剩余存储空间 ext4
- 【网络编程3】网络编程基础-arp请求(局域网主机扫描)
ARP协议 ARP(Add ress Resolution Protocol)地址解析协议位于数据链路层,是根据IP地址获取MAC地址的一个协议. ARP 查看指令 arp -a 显示所有接口的当前A ...
- python中argparse模块用法实例详解
python中argparse模块用法实例详解 这篇文章主要介绍了python中argparse模块用法,以实例形式较为详细的分析了argparse模块解析命令行参数的使用技巧,需要的朋友可以参考下 ...
- Project Euler Problem8
Largest product in a series Problem 8 Find the greatest product of five consecutive digits in the 10 ...
- centos 6.5环境利用iscsi搭建SAN网络存储服务及服务端target和客户端initiator配置详解
一.简介 iSCSI(internet SCSI)技术由IBM公司研究开发,是一个供硬件设备使用的.可以在IP协议的上层运行的SCSI指令集,这种指令集合可以实现在IP网络上运行SCSI协议,使其能够 ...
- centos下常用文件管理命令
fdisk d 删除分区 n:新建一个分区 p:列出已有分区 t:调整分区ID l:列出内核支持的分区id w:保存退出 q:不保存退出 ...
- K最近邻kNN-学习笔记
# -*- coding: utf-8 -*- """ Created on Thu Jan 24 09:34:32 2019 1. 翼尾花数据 2. 用 KNeighb ...
- 怎样使用github
https://www.zhihu.com/question/20070065 https://www.shiyanlou.com/courses/868/labs/3163/document 初次尝 ...
- 多CPU,多核,多进程,多线程
当面临这些问题的时候,有两个关键词无法绕开,那就是并行和并发. 首先,要先了解几个概念: 1.进程是程序的一次执行. 2.进程是资源分配的基本单位(调度单位). 3.一个进程可以包括多个线程. 4.在 ...
- python 全栈开发,Day69(Django的视图层,Django的模板层)
昨日内容回顾 相关命令: 1 创建项目 django-admin startproject 项目名称 2 创建应用 python manage.py startapp app名称 3 启动项目 pyt ...