Codeforces 316C2 棋盘模型
Let’s move from initial matrix to the bipartite graph. The matrix elements (i, j) for which i + j are even should be place to one part, the matrix elements (i, j) for which i + j are uneven should be place to another part. The edges are corresponding to squares which are situated side by side. After that let’s weigh the edges. The edges which connect equal elements of matrix have weights 0, for unequal elements – weight 1. After that the problem is reduced to finding of the maximum independent edge set with minimal weight. Substantiation of above-stated is following: an answer to the problem represents a partitioning of initial matrix for pairs. Note that for any partitioning minimal number of changing matrix elements corresponds to the number of pairs on unequal elements. So in the optimal partitioning the number of pairs of equal elements is maximum. For solving minimum-cost flow problem is needed to use some effective algorithm. For example, Dijkstra algorithm with heap adding conversion of edges weights from Johnson's algorithm.
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1e5+11;
const int oo = 0x3f3f3f3f;
int to[maxn<<1],cost[maxn<<1],cap[maxn<<1],flow[maxn<<1],nxt[maxn<<1];
int head[maxn],tot;
void init(){
memset(head,-1,sizeof head);
tot=0;
}
void add(int u,int v,int c,int w){
to[tot]=v;
cap[tot]=c;
flow[tot]=0;
cost[tot]=w;
nxt[tot]=head[u];
head[u]=tot++;
swap(u,v);
to[tot]=v;
cap[tot]=0;
flow[tot]=0;
cost[tot]=-w;
nxt[tot]=head[u];
head[u]=tot++;
}
struct QUEUE{
int que[maxn];
int front,rear;
void init(){front=rear=0;}
void push(int x){que[rear++]=x;}
int pop(){return que[front++];}
bool empty(){return front==rear;}
}que;
int n,m,s,t;
bool vis[maxn];
int pre[maxn],dis[maxn];
bool spfa(){
que.init();
memset(vis,0,sizeof vis);
memset(pre,-1,sizeof pre);
memset(dis,oo,sizeof dis);
que.push(s);vis[s]=1;dis[s]=0;
while(!que.empty()){
int u=que.pop(); vis[u]=0;
for(int i = head[u]; ~i; i = nxt[i]){
int v=to[i],c=cap[i],f=flow[i],w=cost[i];
if(c>f&&dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
pre[v]=i;
if(!vis[v]){
que.push(v);
vis[v]=1;
}
}
}
}
if(dis[t]==oo) return 0;
else return 1;
}
int mcmf(){
int mc=0,mf=0;
while(spfa()){
int tf=oo+1;
for(int i = pre[t]; ~i; i = pre[to[i^1]]){
tf=min(tf,cap[i]-flow[i]);
}
mf+=tf;
for(int i = pre[t]; ~i; i = pre[to[i^1]]){
flow[i]+=tf;
flow[i^1]-=tf;
}
mc+=dis[t]*tf;
}
return mc;
}
#define rep(i,j,k) for(int i = j; i <= k; i++)
#define repp(i,j,k) for(int i = j; i < k; i++)
#define repe(i,u) for(int i = head[u]; ~i; i = nxt[i])
#define scan(a) scanf("%d",&a)
#define scann(a,b) scanf("%d%d",&a,&b)
#define scannn(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define println(a) printf("%d\n",a)
#define printbk(a) printf("%d ",a)
#define print(a) printf("%d",a)
int G[100][100],R,C,n1;
inline int ID(int i,int j){
return (i-1)*C+j;
}
inline int chai(int x){
return R*C+x;
}
inline bool black(int i,int j){
return i+j &1;
}
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
int main(){
while(scann(R,C)!=EOF){
init();
rep(i,1,R) rep(j,1,C) scan(G[i][j]);
s=R*C+1;t=s+1;n=t;
rep(i,1,R){
rep(j,1,C){
if(!black(i,j))continue;
rep(d,0,3){
int xx=i+dx[d],yy=j+dy[d];
if(xx<1||xx>R||yy<1||yy>C)continue;
if(G[xx][yy]==G[i][j]){
add(ID(i,j),ID(xx,yy),1,0);
}
else{
add(ID(i,j),ID(xx,yy),1,1);
}
}
}
}
rep(i,1,R) rep(j,1,C){
if(black(i,j)) add(s,ID(i,j),1,0);
else add(ID(i,j),t,1,0);
}
println(mcmf());
}
return 0;
}
Codeforces 316C2 棋盘模型的更多相关文章
- D. Three Pieces(dp,array用法,棋盘模型)
https://codeforces.com/contest/1065/problem/D 题意 给你一个方阵,里面的数字从1~nn,你需要从标号为1的格子依次走到标号为nn,在每一个格子你有两个决策 ...
- Nanami's Digital Board CodeForces - 434B (棋盘dp)
大意: 给定01矩阵, m个操作, 操作1翻转一个点, 操作2求边界包含给定点的最大全1子矩阵 暴力枚举矩形高度, 双指针统计答案 #include <iostream> #include ...
- Codeforces - tag::flows 大合集 [完坑 x14]
589F 题意:给出n个时间区间,每个区间挑定长的非连续区间,求不同个区间不存在时间冲突的最大定长,输出乘上n 二分图模型+二分长度,左顶点集为区间编号,右顶点集为时间编号(1...10000),汇点 ...
- Codeforces 最大流 费用流
这套题目做完后,一定要反复的看! 代码经常出现的几个问题: 本机测试超时: 1.init函数忘记写. 2.addedge函数写成add函数. 3.边连错了. 代码TLE: 1.前向星边数组开小. 2. ...
- 「2017 山东一轮集训 Day4」棋盘(费用流)
棋盘模型 + 动态加边 #include<cstdio> #include<algorithm> #include<iostream> #include<cs ...
- 关于三目运算符与if语句的效率与洛谷P2704题解
题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图.在每一格平原地形上最 ...
- [SCOI2005]互不侵犯King
题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. ——by洛谷 https://www. ...
- [入门向选讲] 插头DP:从零概念到入门 (例题:HDU1693 COGS1283 BZOJ2310 BZOJ2331)
转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7326874.html 最近搞了一下插头DP的基础知识……这真的是一种很锻炼人的题型…… 每一道题的状态都不一样 ...
- JAVA课程设计+五子棋(团队博客)
JAVA课程设计 利用所学习的JAVA知识设计一个五子棋小游戏 1.团队名称.团队成员介绍(菜鸟三人组) 杨泽斌[组长]:201521123049 网络1512 叶文柠[组员]:20152112305 ...
随机推荐
- java GC是在什么时候,对什么东西,做了什么事情?
1.新生代有一个Eden区和两个survivor区,首先将对象放入Eden区,如果空间不足就向其中的一个survivor区上放,如果仍然放不下就会引发一次发生在新生代的minor GC,将存活的对象放 ...
- 2用java代码实现冒泡排序算法(转载)
import java.util.Scanner; public class Maopao { public static void main(String[] args) { System.out. ...
- p2657 windy数
传送门 分析 首先这是一个询问一段区间内的个数的问题,所以我们可以用差分的思想用sum(R)-sum(L-1).然后我们考虑如何求出sum(n),我们用dp[i][j][k][t]表示考虑到第i位,最 ...
- ARC073D Simple Knapsack
传送门 题目大意 给你n个物品,你有一个容量为W的背包,每一个物品都有它的重量和价值,让你从n个中选取若干个,使得总重量不超过背包的上限,而且使得价值最大. 分析 首先我们不难发现由于W很大,所以这并 ...
- 后台传Map到ftl
userInfo是后台传过来的Map <#list userInfo?keys as key> <tr > <td class="case_id" d ...
- Spark 1.4.1中Beeline使用的gc overhead limit exceeded
最近使用SparkSQL做数据的打平操作,就是把多个表的数据经过关联操作导入到一个表中,这样数据查询的过程中就不需要在多个表中查询了,在数据量大的情况下,这样大大提高了查询效率. 我启动了thri ...
- spring、spring mvc以及IOC的阅读
spring vs spring-mvc spring是应用级框架 spring mvc只是一个mvc框架 spring现在包含很多子模块,我们用的最多的是依赖注入. spring模块可分为以下: C ...
- 处理器(也就是执行流程图上面的controller)执行逻辑(十)
处理器继承自:AbstractController,MultiActionController 一.AbstractController 如上图,可以分析出AbstractController用的 ...
- linux手动安装配置 mysql5.7
本文原出处地址 https://www.cnblogs.com/mujingyu/p/7689116.html 一.安装前的检查 1.1 检查 linux 系统版本 [root@localhost ...
- asp.net core 之多语言国际化自定义资源文件
先说说 asp.net core 默认的多语言和国际化. 官方文档 一:基本使用方法 先要安装 包 Microsoft.AspNetCore.Mvc.Localization (依赖 Microsof ...