SRM 558 SurroundingGame
题意:
给定一个网格,每个网格有选取代价和占据收益。每个点被占据,需要满足以下两个条件至少一个条件:1.被选取 2.邻近方格都被选取(有公共边被称为邻近) 不一定要占据所有方格,求最大收益。
输入说明
第一行两个数 n,m(n,m ≤ 20),表示矩形的长和宽。
接下来 n 行,每行是 m 个字符组成的字符串,描述投资的花费。
接下来 n 行,每行是 m 个字符组成的字符串,表示该格子的收益。
花费和收益按照一种奇葩的方式给出:
字符
数
‘0’-’9’
0-9
‘a’-’z’
10-35
‘A’-’Z’
36-61
输出说明
一个数,表示收益的和减去投资的和的最大值。
样例 1
2 2
21
12
21
12
答案:4
样例 2
2 2
ZZ
ZZ
11
11
答案: 0
样例 3
3 3
XXX
XXX
XXX
aaa
aZa
aaa
答案: 2
样例 4
2 4
asam
atik
123A
45BC
答案: 71
样例 5
98
IIIIIIII
IIWWWWII
IIWIIIII
IIWIIIII
IIWWWWII
IIIIIWII
IIIIIWII
IIWWWWII
IIIIIIII
IIIIIIII
II0000II
II0II0II
II0II0II
II0000II
II0II0II
II0II0II
II0000II
IIIIIIII
答案: 606
先黑白染色
源点S点连白点,汇点T点连黑点
现将所有利润加起来,显然要减去一部分花费和利润
我们求最小的使利润合法的要减去一部分花费和利润
然后转化为求最小割,设收益边和花费边
首先考虑几种情况
1.保留一个点的花费边,保留收益边(即不投资拿到利润)
那么此刻如果相邻有点没有割掉花费边,那么就会有流
2.割掉一个花费边,保留收益边(投资一个点)
3.割掉一个收益边,保留花费边(不投资该点)
只考虑前2中情况我们可以建出:

考虑第3种情况:
因为放弃这个格子的收益,代表着相邻的格子的收益必须要靠它自己的花费
于是有了如下建图

图片转自ZYYS
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
struct Node
{
int next,to,cap;
}edge[];
int head[],num=,inf=1e9,S,T,dist[],n,m,a[][],b[][],ans,tot,pre[][],nxt[][],col[][];
char s1[][],s2[][];
void add(int u,int v,int cap)
{
num++;
edge[num].next=head[u];
head[u]=num;
edge[num].to=v;
edge[num].cap=cap;
num++;
edge[num].next=head[v];
head[v]=num;
edge[num].to=u;
edge[num].cap=;
}
bool bfs()
{int i;
queue<int>Q;
for (i=S;i<=T;i++)
dist[i]=-;
dist[S]=;
Q.push(S);
while (Q.empty()==)
{
int u=Q.front();
Q.pop();
for (i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if (edge[i].cap==||dist[v]!=-) continue;
dist[v]=dist[u]+;
Q.push(v);
}
}
if (dist[T]==-) return ;
return ;
}
int dfs(int x,int flow,int des)
{int i;
if (x==des) return flow;
if (flow<=) return ;
int res=,tmp;
for (i=head[x];i;i=edge[i].next)
{
int v=edge[i].to;
if (dist[v]==dist[x]+&&edge[i].cap)
{
tmp=dfs(v,min(edge[i].cap,flow-res),des);
edge[i].cap-=tmp;
edge[i^].cap+=tmp;
res+=tmp;
if (res==flow) return res;
}
}
return res;
}
int Maxflow()
{
int as=;
while (bfs())
{
int a=;
while (a=dfs(S,inf,T)) as+=a;
}
return as;
}
int main()
{int i,j;
cin>>n>>m;
for (i=;i<n;i++)
{
scanf("%s",s1[i]);
}
for (i=;i<n;i++)
{
scanf("%s",s2[i]);
}
for (i=;i<=n;i++)
{
for (j=;j<=m;j++)
{
if (s1[i-][j-]>=''&&s1[i-][j-]<='')
a[i][j]=s1[i-][j-]-'';
else if (s1[i-][j-]>='a'&&s1[i-][j-]<='z')
a[i][j]=s1[i-][j-]-'a'+;
else a[i][j]=s1[i-][j-]-'A'+;
}
}
for (i=;i<=n;i++)
{
for (j=;j<=m;j++)
{
if (s2[i-][j-]>=''&&s2[i-][j-]<='')
b[i][j]=s2[i-][j-]-'';
else if (s2[i-][j-]>='a'&&s2[i-][j-]<='z')
b[i][j]=s2[i-][j-]-'a'+;
else b[i][j]=s2[i-][j-]-'A'+;
ans+=b[i][j];
}
}
S=;tot=;
for (i=;i<=n;i++)
{
for (j=;j<=m;j++)
{
pre[i][j]=++tot;nxt[i][j]=++tot;
col[i][j]=(i+j)&;
}
}
T=++tot;
for (i=;i<=n;i++)
{
for (j=;j<=m;j++)
{
if (col[i][j]==)
{
add(S,pre[i][j],a[i][j]);
add(pre[i][j],nxt[i][j],b[i][j]);
if (i-)
add(pre[i][j],nxt[i-][j],inf),add(nxt[i][j],pre[i-][j],inf);
if (i<n)
add(pre[i][j],nxt[i+][j],inf),add(nxt[i][j],pre[i+][j],inf);
if (j-)
add(pre[i][j],nxt[i][j-],inf),add(nxt[i][j],pre[i][j-],inf);
if (j<m)
add(pre[i][j],nxt[i][j+],inf),add(nxt[i][j],pre[i][j+],inf);
}
else
{
add(pre[i][j],T,a[i][j]);
add(nxt[i][j],pre[i][j],b[i][j]);
}
}
}
cout<<ans-Maxflow();
}
SRM 558 SurroundingGame的更多相关文章
- TopCoder SRM 558 Div 1 - Problem 1000 SurroundingGame
传送门:https://284914869.github.io/AEoj/558.html 题目简述 一个人在一个n * m棋盘上玩游戏,想要占领一个格子有两个方法: 在这个格子放一个棋子. 这个 ...
- 记第一次TopCoder, 练习SRM 583 div2 250
今天第一次做topcoder,没有比赛,所以找的最新一期的SRM练习,做了第一道题. 题目大意是说 给一个数字字符串,任意交换两位,使数字变为最小,不能有前导0. 看到题目以后,先想到的找规律,发现要 ...
- SRM 513 2 1000CutTheNumbers(状态压缩)
SRM 513 2 1000CutTheNumbers Problem Statement Manao has a board filled with digits represented as St ...
- SRM 510 2 250TheAlmostLuckyNumbersDivTwo(数位dp)
SRM 510 2 250TheAlmostLuckyNumbersDivTwo Problem Statement John and Brus believe that the digits 4 a ...
- UVA 558 判定负环,spfa模板题
1.UVA 558 Wormholes 2.总结:第一个spfa,好气的是用next[]数组判定Compilation error,改成nexte[]就过了..难道next还是特殊词吗 题意:科学家, ...
- SRM 657 DIV2
-------一直想打SRM,但是感觉Topcoder用起来太麻烦了.题目还是英文,不过没什么事干还是来打一打好了.但是刚注册的号只能打DIV2,反正我这么弱也只适合DIV2了.. T1: 题目大意: ...
- uva 558 - Wormholes(Bellman Ford判断负环)
题目链接:558 - Wormholes 题目大意:给出n和m,表示有n个点,然后给出m条边,然后判断给出的有向图中是否存在负环. 解题思路:利用Bellman Ford算法,若进行第n次松弛时,还能 ...
- SRM DIV1 500pt DP
SRM 501 DIV1 500pt SRM 502 DIV1 500pt SRM 508 DIV1 500pt SRM 509 DIV1 500pt SRM 511 DIV1 500pt SRM 5 ...
- TC srm 673 300 div1
TC srm.673 300 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 Description 给你n(n<=50)匹马和n个人,一匹马和一个人能 ...
随机推荐
- 4c语言的第0次作业
1.你认为大学的学习生活.同学关系.师生关系应该是怎样? 我认为大学的学习生活应该是充实有意义的,有对学习的激情又有与伙伴相知的愉悦. 我认为同学关系应该是互相尊重,互相学习,坦诚相待. 我认为师生关 ...
- 1013团队Beta冲刺day7
项目进展 李明皇 今天解决的进度 部分数据传递和使用逻辑测试 林翔 今天解决的进度 服务器端查看个人发布的action,修改已发布消息状态的action,仍在尝试使用第三方云存储功能保存图片 孙敏铭 ...
- Python 实现队列
操作 Queue() 创建一个空的队列 enqueue(item) 往队列中添加一个item元素 dequeue() 从队列头部删除一个元素 is_empty() 判断一个队列是否为空 size() ...
- edittext实现自动查询,刷新listview
mEdittextqueryvalue.addTextChangedListener(new TextWatcher() { @Override pub ...
- 手把手教你 LabVIEW 串口仪器控制——VISA 驱动下载安装篇
仪器控制,核心在于 VISA 函数..有些仪器可能不需要 VISA,有自己的 DLL 什么的,我就管不着. 正常情况下,大家安装的 LabVIEW,都是不带 VISA 驱动 ...
- 201421123042 《Java程序设计》第6周学习总结
1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图或相关笔记,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰 ...
- Scala 操作符与提取器
实际上Scala没有操作符, 只是以操作符的格式使用方法. 操作符的优先级取决于第一个字符(除了赋值操作符), 而结合性取决于最后一个字符 Scala的操作符命名更加灵活:) 操作符 中置操作符(In ...
- img加载卡顿,解决办法
我觉得我在这个项目里遇到了太多的第一次.比如上一篇博文:在在360.UC等浏览器,img不加载原因. 当前情况是:图片加载缓慢,图片加载时出现卡顿. 上图:我缩放了图片,估计有点变形.能说明情况就行, ...
- 第一篇:Python入门
一.编程与编程语言 编程的目的: 计算机的发明,是为了用机器取代/解放人力,而编程的目的则是将人类的思想流程按照某种能够被计算机识别表达方式传递给计算机,从而达到让计算机能够像人脑/电脑一样自动执行的 ...
- Node入门教程(7)第五章:node 模块化(下) npm与yarn详解
Node的包管理器 JavaScript缺少包结构的定义,而CommonJS定义了一系列的规范.而NPM的出现则是为了在CommonJS规范的基础上,实现解决包的安装卸载,依赖管理,版本管理等问题. ...