CodeChef BIBOARD: Binary Board 命题报告
这道题当时有了一点模糊的想法之后,构思了一整天……
题意:
有一\(N \times M\)网格,每一格可以是白色或黑色。令\(B_i\)表示\(i \times i\)的纯黑子网格数量(子网格是指原网格的子矩形,必须连通),\(W_i\)表示\(i \times i\)的纯白子网格数量。给定两个非负整数数组\(CW\)和\(CB\),定义这个网格的代价为$$\sum_{i=1}^{\mathrm{min}(N, M)} CB_i \cdot B_i + CW_i \cdot W_i$$
现在网格的有些位置颜色确定,让你给剩下的位置钦定颜色,使代价最大。
\(1 \leq N \cdot M \leq 500\)
思路:
注意到题目可以做这样的变形:
1、如果\(N<M\),把它们交换。
2、令\(SB\)为\(CB\)的前缀和,\(SW\)同理。
3、定义下标从\(-M\)到\(M\)的数组\(S\),满足:
当\(i>0\),\(S_i=SB_i\);
当\(i<0\),\(S_i=SW_{-i}\)。
4、对每一个格子\((i,j)\),试着确定以\((i,j)\)为左上角的纯色正方形的最大边长。如果该正方形为黑色,记\(l_{i,j}\)等于该最大边长;否则\(l_{i,j}\)等于边长的相反数。
5、目标:最大化\(\sum S_{l_{i,j}}\)。
由于\(l_{i,j}\)之间的关系错综复杂,互相制约,考虑使用网络流,并尝试最小割模型。
对于每一个格子\((i,j)\)和\(-N\)到\(N\)之间的整数\(l\),我们都建立一个点\((i,j,l)\),并按以下方式加边:
1、对于\(l<0\),\((i,j,l) ~~ -> ~~ (i,j,l+1)\),代价为\(inf-S_l\)。
2、对于\(l>0\),\((i,j,l-1)~~ ->~~ (i,j,l)\),代价为\(inf-S_l\)。
3、\(S~~ ->~~ (i,j,-n)\),代价为\(2 \cdot inf\)。
4、\((i,j,n)~~->~~T\),代价为\(2 \cdot inf\)。
注意在以上建立的边中,割掉一条边意味着对于\((i,j)\),取\(l_{i,j}\)等于这条边对应的\(l\)。对于颜色已经钦定的点,\((i,j,0)\)的某一侧都取两倍无穷大即可。
在边权上加上\(inf\),是为了保证对于特定的\((i,j)\),在如上所述的所有边中,只会割掉一条。
为了保证盘面合法,我们还要考虑两个约束条件(易证它们是充分必要的):
1、两个颜色不同的纯色正方形不能有公共格子;
2、\(|l_{i,j}|\)必须恰好等于,以\((i,j)\)为左上角的纯色正方形的最大边长。
定义\(dist((i,j),(k,l))=max\{i-k,j-l\}\),则我们可以把第一个约束条件写为:
Rule 1:当\(l_{i,j}>0\)(表示网格\((i,j)\)为黑),对于所有的\(k \leq i\)和\(l \leq j\)(表示左上方的所有正方形),有\(l_{k,l}>-dist((i,j),(k,l))\)(表示\((i,j)\)不被白色正方形覆盖)。
Rule 2:当\(l_{i,j}<0\),对于所有的\(k \leq i\)和\(l \leq j\),有\(l_{k,l}<dist((i,j),(k,l))\)。
而思考发现,第二个约束条件(注意不是Rule 2)等价于:
Rule 3:对于合法的盘面,一定不可能把某一个\(l_{i,j}\)的绝对值增加1(符号不变),而不破坏Rule 1、Rule2。换句话说,所有\(l_{i,j}\)都取到极大值。
考虑如何构图以保证符合这3条规则。
不妨改写一下Rule 1和Rule 2:
Rule 1:\(l_{i,j}>0 \Rightarrow l_{k,l}>-dist((i,j),(k,l))\)
Rule 2:\(l_{i,j}<0 \Rightarrow l_{k,l}<dist((i,j),(k,l))\)
为了强制要求最终的割集满足这两个条件,我们对于所有的\(k \leq i\)和\(l \leq j\),连以下两条权值为\(2 \cdot inf\)的边:
1、\((i,j,0)~~->~~(k,l,-dist((i,j),(k,l)))\)
2、\((k,l,dist((i,j),(k,l)))~~->~~(i,j,0)\)
易见经过这样的连边后,如果割集不满足Rule 1或Rule 2,剩下的边中就会存在\(S-T\)路径,割集就不是合法的割集。目的达成。
而对于Rule 3:由于\(CB\)和\(CW\)中的数都非负,所以\(SB\)和\(SW\)都是不下降序列。那么如果可以把某一个\(l_{i,j}\)的绝对值增加1而不破坏Rule 1、Rule2,我们的最小割(实则为最大流)算法一定可以直接在这里增广一次,得到更优解。于是易证,先前构出的图的任何一组最小割一定满足Rule 3。
综上,\(N \cdot M \cdot inf - MinCut\)就是答案。实践中Dinic在这题上跑得飞快。
代码:
#include <bits/stdc++.h>
using namespace std;
#define inf 10000000000000LL
#define iinf 2000000000
#define linf 1000000000000000000LL
#define ulinf 10000000000000000000ull
#define MOD1 1000000007LL
#define mpr make_pair
typedef long long LL;
typedef unsigned long long ULL;
typedef unsigned long UL;
typedef unsigned short US;
typedef pair < int , int > pii;
clock_t __stt;
inline void TStart(){__stt=clock();}
inline void TReport(){printf("\nTaken Time : %.3lf sec\n",(double)(clock()-__stt)/CLOCKS_PER_SEC);}
template < typename T > T MIN(T a,T b){return a<b?a:b;}
template < typename T > T MAX(T a,T b){return a>b?a:b;}
template < typename T > T ABS(T a){return a>0?a:(-a);}
template < typename T > void UMIN(T &a,T b){if(b<a) a=b;}
template < typename T > void UMAX(T &a,T b){if(b>a) a=b;}
namespace mincut{
const int S=24666,T=24233;
struct edge{
int v,r;
LL f;
void set(int V,int R,LL F){
v=V;r=R;f=F;
}
};
vector < edge > adj[25000];
int cur[25000],dis[25000];
void init(){
int i;
for(i=0;i<25000;++i) adj[i].clear();
}
void addedge(int u,int v,LL f){
edge T;
T.set(v,(int)adj[v].size(),f);
adj[u].push_back(T);
T.set(u,(int)adj[u].size()-1,0LL);
adj[v].push_back(T);
}
void bfs(){
queue < int > Q;
Q.push(S);
dis[S]=0;
while(!Q.empty()){
int i,cv=Q.front();
Q.pop();
for(i=0;i<(int)adj[cv].size();++i){
if(adj[cv][i].f>0LL && dis[adj[cv][i].v]==-1){
dis[adj[cv][i].v]=dis[cv]+1;
Q.push(adj[cv][i].v);
}
}
}
}
LL dfs(int ver,LL cap){
if(ver==T) return cap;
int i;
for(i=cur[ver];i<(int)adj[ver].size();++i){
cur[ver]=i;
edge &E=adj[ver][i];
if(E.f>0LL && dis[E.v]>dis[ver]){
LL ret=dfs(E.v,MIN(cap,E.f));
if(ret>0LL){
E.f-=ret;
adj[E.v][E.r].f+=ret;
return ret;
}
}
}
return 0LL;
}
LL maxflow(){
LL ret=0LL,dlt;
while(1){
memset(dis,-1,sizeof(dis));
memset(cur,0,sizeof(cur));
bfs();
if(dis[T]==-1) return ret;
dlt=1LL;
while(dlt){
dlt=dfs(S,inf*2LL);
ret+=dlt;
}
}
}
};
int n,m,stt[505][505],tmp[505][505],cb[505],cw[505];
LL sb[505],sw[505];
int getbit(){
char c=getchar();
while(c!='0'&&c!='1'&&c!='?') c=getchar();
return (c=='?'?-1:(c=='1'));
}
int enc(int i,int j,int k){
return k*n*m+(i*m)+j;
}
void solve(){
// inputting start
// 数据结构记得初始化! n,m别写反!
mincut::init();
scanf("%d%d",&n,&m);
int i,j,k,l;
for(i=0;i<n;++i){
for(j=0;j<m;++j){
stt[i][j]=getbit();
}
}
for(i=0;i<n&&i<m;++i) scanf("%d",cw+i);
for(i=0;i<n&&i<m;++i) scanf("%d",cb+i);
#ifdef LOCAL
TStart();
#endif
// calculation start
// 数据结构记得初始化! n,m别写反!
if(n>m){
for(i=0;i<n;++i){
for(j=0;j<m;++j){
tmp[j][i]=stt[i][j];
}
}
memcpy(stt,tmp,sizeof(tmp));
swap(n,m);
}
sb[0]=(LL)cb[0];
sw[0]=(LL)cw[0];
for(i=1;i<n;++i){
sb[i]=sb[i-1]+(LL)cb[i];
sw[i]=sw[i-1]+(LL)cw[i];
}
for(i=0;i<n;++i){
for(j=0;j<m;++j){
int maxl=MIN(n-i,m-j);
for(k=0;k<n;++k){
if(stt[i][j]!=1 && n-k<=maxl)
mincut::addedge(enc(i,j,k),enc(i,j,k+1),inf-sw[n-k-1]);
else
mincut::addedge(enc(i,j,k),enc(i,j,k+1),inf*2LL);
}
for(k=0;k<n;++k){
if(stt[i][j]!=0 && k<maxl)
mincut::addedge(enc(i,j,n+k),enc(i,j,n+k+1),inf-sb[k]);
else
mincut::addedge(enc(i,j,n+k),enc(i,j,n+k+1),inf*2LL);
}
mincut::addedge(mincut::S,enc(i,j,0),inf*2LL);
mincut::addedge(enc(i,j,n*2),mincut::T,inf*2LL);
for(k=0;k<=i;++k){
for(l=0;l<=j;++l){
if(k==i&&l==j) continue;
int dist=MIN(MAX(i-k,j-l),n);
mincut::addedge(enc(i,j,n),enc(k,l,n-dist),inf*2LL);
mincut::addedge(enc(k,l,n+dist),enc(i,j,n),inf*2LL);
}
}
}
}
printf("%lld\n",inf*(LL)n*(LL)m-mincut::maxflow());
#ifdef LOCAL
TReport();
#endif
}
int main(){
int t;
scanf("%d",&t);
while(t--) solve();
return 0;
}
CodeChef BIBOARD: Binary Board 命题报告的更多相关文章
- 【LeetCode】863. All Nodes Distance K in Binary Tree 解题报告(Python)
[LeetCode]863. All Nodes Distance K in Binary Tree 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http ...
- 【LeetCode】297. Serialize and Deserialize Binary Tree 解题报告(Python)
[LeetCode]297. Serialize and Deserialize Binary Tree 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode ...
- 【LeetCode】331. Verify Preorder Serialization of a Binary Tree 解题报告(Python)
[LeetCode]331. Verify Preorder Serialization of a Binary Tree 解题报告(Python) 标签: LeetCode 题目地址:https:/ ...
- 【LeetCode】662. Maximum Width of Binary Tree 解题报告(Python)
[LeetCode]662. Maximum Width of Binary Tree 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://leetcode.co ...
- 2019国家集训队论文《整点计数》命题报告 学习笔记/Min25
\(2019\)国家集训队论文<整点计数>命题报告 学习笔记/\(Min25\) 补了个大坑 看了看提交记录,发现\(hz\)的\(xdm\)早过了... 前置知识,\(HAOI\)< ...
- 【LeetCode】236. Lowest Common Ancestor of a Binary Tree 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...
- LeetCode 606 Construct String from Binary Tree 解题报告
题目要求 You need to construct a string consists of parenthesis and integers from a binary tree with the ...
- LeetCode 993 Cousins in Binary Tree 解题报告
题目要求 In a binary tree, the root node is at depth 0, and children of each depth k node are at depth k ...
- LeetCode 226 Invert Binary Tree 解题报告
题目要求 Invert a binary tree. 题目分析及思路 给定一棵二叉树,要求每一层的结点逆序.可以使用递归的思想将左右子树互换. python代码 # Definition for a ...
随机推荐
- Azkaban3.X的安装(2018年8月19日最新版本)
参考文章: 1.http://azkaban.github.io/azkaban/docs/latest/ 2.http://blog.csdn.net/gaoqida/article/details ...
- 在vs2015中使用附加进程的方式调试IIS中的页面
发布网站至IIS-附加到进程调试 Internet Information Services(IIS,互联网信息服务),是由微软公司提供的基于运行Microsoft Windows的互联网基本服务. ...
- python3.6安装总结
安装Python 3.6 过程中出现了一些问题,导致费时费力.因此把自己安装过程中出现的问题写出来,以备大家查看. 第一步:比较简单的一种安装方法是直接安装Anacanda3 python即可,这时可 ...
- [零基础学JAVA]Java SE基础部分-03. 运算符和表达式
转自:http://redking.blog.51cto.com/27212/116751 1.课程名称:运算符.表达式 讲解了JAVA中各种运算符的使用,包括与.或.非.大于.小于等. 2.知识点 ...
- 【[AHOI2005]病毒检测】
\(Trie\) 树+搜索 我用的是\(dfs\) 首先对于将所有的RNA片段都建到\(Trie\)树里去,之后来匹配那个模板串就好了 如果是匹配的位置是字母,那么我们就继续往下匹配 如果是\(?\) ...
- 理解JavaScript闭包(closure)
闭包听了很多次了,可是到底有那些具体的用法还是不清楚,看了<JavaScript高级程序设计>,有点明白了. 1.闭包的定义: 闭包其实就是一个函数,而这个函数有点特别,它能够访问另一个函 ...
- Linux 文件压缩与解压相关
tar [-cxtzjvfpPN] 文件与目录 .... 参数:-c :建立一个压缩文件的参数指令-x :解开一个压缩文件的参数指令 -t :查看压缩文件里面的文件 特别注意: c/x/t 同时只能存 ...
- mysql数据库迁移到oracle数据库后 如何删除相同的数据
mysql数据库迁移到oracle数据库后 如何删除相同的数据 首先搞清楚有多少数据是重复的 select pid from product group by pid having count(pid ...
- Layered Architecture 分层架构
分层的价值在于每一层都只代表程序中的某一特定方面.这种限制使每个方面的设计都更具有内聚性,更容易解释. 大多数成功的架构使用的都是包括下面这四个概念层的某个版本
- 竞赛题解 - Karp-de-Chant Number(BZOJ-4922)
Karp-de-Chant Number(BZOJ-4922) - 竞赛题解 进行了一次DP的练习,选几道题写一下博客~ 标签:BZOJ / 01背包 / 贪心 『题目』 >> There ...