这道题当时有了一点模糊的想法之后,构思了一整天……

题意:

有一\(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 命题报告的更多相关文章

  1. 【LeetCode】863. All Nodes Distance K in Binary Tree 解题报告(Python)

    [LeetCode]863. All Nodes Distance K in Binary Tree 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http ...

  2. 【LeetCode】297. Serialize and Deserialize Binary Tree 解题报告(Python)

    [LeetCode]297. Serialize and Deserialize Binary Tree 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode ...

  3. 【LeetCode】331. Verify Preorder Serialization of a Binary Tree 解题报告(Python)

    [LeetCode]331. Verify Preorder Serialization of a Binary Tree 解题报告(Python) 标签: LeetCode 题目地址:https:/ ...

  4. 【LeetCode】662. Maximum Width of Binary Tree 解题报告(Python)

    [LeetCode]662. Maximum Width of Binary Tree 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://leetcode.co ...

  5. 2019国家集训队论文《整点计数》命题报告 学习笔记/Min25

    \(2019\)国家集训队论文<整点计数>命题报告 学习笔记/\(Min25\) 补了个大坑 看了看提交记录,发现\(hz\)的\(xdm\)早过了... 前置知识,\(HAOI\)< ...

  6. 【LeetCode】236. Lowest Common Ancestor of a Binary Tree 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  7. LeetCode 606 Construct String from Binary Tree 解题报告

    题目要求 You need to construct a string consists of parenthesis and integers from a binary tree with the ...

  8. 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 ...

  9. LeetCode 226 Invert Binary Tree 解题报告

    题目要求 Invert a binary tree. 题目分析及思路 给定一棵二叉树,要求每一层的结点逆序.可以使用递归的思想将左右子树互换. python代码 # Definition for a ...

随机推荐

  1. Windows 编译 MQTT C++ Client

    MQTT MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分.该协议支持所有平台,几乎可 ...

  2. MapReduce过程详解(基于hadoop2.x架构)

    本文基于hadoop2.x架构详细描述了mapreduce的执行过程,包括partition,combiner,shuffle等组件以及yarn平台与mapreduce编程模型的关系. mapredu ...

  3. 漫谈 Clustering (4): Spectral Clustering

    转:http://blog.pluskid.org/?p=287 如果说 K-means 和 GMM 这些聚类的方法是古代流行的算法的话,那么这次要讲的 Spectral Clustering 就可以 ...

  4. 云来储存型XSS漏洞+越权修改应用封面

    0x001. 今天本来想看看场景应用有什么新功能没,于是乎随便打开了一个场景应用,然后上传了一张图片修改下封面,结果我看到firefox 网络竟然有2个post,不由得勾起我的好奇心,好奇害死猫嘿嘿. ...

  5. phoneGap的Android下编写phonegap 插件

    一. javascript 端的编写  第一个参数 成功的回调函数 第二个参数 失败的回调函数 第三个参数 是插件的类名称,也就是后台java文件的类名 第四个参数 执行的 action 名称     ...

  6. hdu-2837 Calculation---指数循环节

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2837 题目大意: 已知f(0) = 1,0^0 =1,[注意,0的其他任意次方为0,虽然题没有直接给 ...

  7. springboot+mybatis+shiro——shiro简介

    转载:[一]shiro入门 之 Shiro简介 一.shiro介绍: 官方网址:http://shiro.apache.org/introduction.html,shiro的功能包括:认证.授权.加 ...

  8. Java之生成Pdf并对Pdf内容操作

    虽说网上有很多可以在线导出Pdf或者word或者转成png等格式的工具,但是我觉得还是得了解知道是怎么实现的.一来,在线免费转换工具,是有容量限制的,达到一定的容量时,是不能成功导出的;二来,业务需求 ...

  9. spring配置redis(xml+java方式)(最底层)

    条件:引用好架包 <dependency> <groupId>org.springframework.data</groupId> <artifactId&g ...

  10. js去除空格(trim方法)

    /** * 去空格 */ String.prototype.trim=function(){ return this.replace(/(^\s*)|(\s*$)/g, ""); ...