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

题意:

有一\(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. AutoHotkey批量L版代码转H2的vim脚本

    原脚本尽量用表达式的语法写,错误会比较少,比如"If a=", "fun(a=1)"这种语法在V2会出错文件放vim的autoload目录下,可使用以下map使 ...

  2. January 25 2017 Week 4 Wednesday

    In every triumph, there's a lot of try. 每个胜利背后都有许多尝试. There's a lot of try behind every success, and ...

  3. php生成csv文件并提供下载及相关注意事项

    1.生成文件过程略,只要逗号分割就可以了 2.提供下载加上如下代码: header("Content-type: application/octet-stream"); heade ...

  4. 分布式链路跟踪系统架构SkyWalking和zipkin和pinpoint

    Net和Java基于zipkin的全链路追踪 https://www.cnblogs.com/zhangs1986/p/8966051.html 在各大厂分布式链路跟踪系统架构对比 中已经介绍了几大框 ...

  5. 跳跃表 SkipList【数据结构】原理及实现

    为什么选择跳表 目前经常使用的平衡数据结构有:B树,红黑树,AVL树,Splay Tree, Treep等. 想象一下,给你一张草稿纸,一只笔,一个编辑器,你能立即实现一颗红黑树,或者AVL树出来吗? ...

  6. Django 模型中字段类型的ImageField

    model_pic = models.ImageField(upload_to = 'pic_folder/', default = 'pic_folder/None/no-img.jpg') 参数u ...

  7. HDU 4676 Sum Of Gcd 【莫队 + 欧拉】

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=4676 Sum Of Gcd Time Limit: 10000/5000 MS (Java/Others ...

  8. 华为交换机SSH配置

    设备:S5700 一.在本地设备服务端生成秘钥对 [Huawei]rsa local-key-pair create 二.配置VTY [Huawei]user-interface vty 0 4进入虚 ...

  9. Mark一下在模仿团购App搭建页面时犯的低级错误

    1.关于Xib拖线错误 2.下面这个错误的根源其实是代码提示时直接敲下了回车,没看仔细,导致后来找了好久才发现该错误,郁闷啊!

  10. C#实现双向链表

    原文:http://www.cnblogs.com/skywang12345/p/3561803.html#a33 没有C#版本的..是不是很方..不过图和说明很好,引用一下 双向链表 双向链表(双链 ...