BZOJ3171 Tjoi2013 循环格
Description
一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子。每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0)。给定一个起始位置(r,c)
,你可以沿着箭头防线在格子间行走。即如果(r,c)是一个左箭头,那么走到(r,c-1);如果是右箭头那么走到(r,c+1);如果是上箭头那么走到(r-1,c);如果是下箭头那么走到(r+1,c);每一行和每一列都是循环的,即如果走出边界,你会出现在另一侧。
一个完美的循环格是这样定义的:对于任意一个起始位置,你都可以i沿着箭头最终回到起始位置。如果一个循环格不满足完美,你可以随意修改任意一个元素的箭头直到完美。给定一个循环格,你需要计算最少需要修改多少个元素使其完美。
Input
第一行两个整数R,C。表示行和列,接下来R行,每行C个字符LRUD,表示左右上下。
Output
一个整数,表示最少需要修改多少个元素使得给定的循环格完美
Sample Input
3 4
RRRD
URLL
LRRR
Sample Output
2
HINT
1<=R,C<=15
这道题怎么做呢?我们很难想出怎么才是最优的决策走法,那么干脆不管他了!
这道题让我们想起了一个经典问题:“给出一个图,判断都少个点在至少一个环里面”。其中一种做法就是跑网络流,每一个点拆成两个,一个进,源点连向它,一个出,它连向汇点,然后跑一下最大流,就得到答案了。
这道题不是差不多嘛?
可以改道,那么我们就连成一张”四通八达”的图,原本的方向费用为0,其余的费用为1。跑一次费用流,答案就是费用了。
/**************************************************************
Problem: 3171
User: geng4512
Language: C++
Result: Accepted
Time:4 ms
Memory:1236 kb
****************************************************************/
#include<algorithm>
#include<cstdio>
#include<cstring>
#define INF 0x3f3f3f3f
#define MAXN 10005
using namespace std;
int n, m, S, T, dd[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
char mp[30][30];
int hsh[200];
struct Node { int v, w, f, nxt; } e[MAXN<<1];
int Adj[MAXN], ecnt = 1, cost, dis[MAXN];
int vis[MAXN];
inline void Add(int u, int v, int w, int f) {
++ ecnt; e[ecnt].v = v; e[ecnt].w = w; e[ecnt].f = f; e[ecnt].nxt = Adj[u]; Adj[u] = ecnt;
++ ecnt; e[ecnt].v = u; e[ecnt].w = -w; e[ecnt].f = 0; e[ecnt].nxt = Adj[v]; Adj[v] = ecnt;
}
bool Upd() {
int tmp = INF;
for(int u = 0; u <= T; ++ u) if(vis[u])
for(int i = Adj[u]; i; i = e[i].nxt)
if(!vis[e[i].v] && e[i].f)
tmp = min(tmp, dis[e[i].v] + e[i].w - dis[u]);
if(tmp == INF) return 0;
for(int u = 0; u <= T; ++ u) if(vis[u]) dis[u] += tmp;
return 1;
}
int Aug(int u, int augco) {
if(u == T) {
cost += dis[S] * augco;
return augco;
}
int augc = augco, delta, v;
vis[u] = 1;
for(int i = Adj[u]; i; i = e[i].nxt) {
v = e[i].v;
if(e[i].f && !vis[v] && dis[u] - e[i].w == dis[v]) {
delta = Aug(v, min(e[i].f, augc));
augc -= delta; e[i].f -= delta; e[i^1].f += delta;
if(!augc) return augco;
}
}
return augco - augc;
}
int ZKW() {
do {
do memset(vis, 0, sizeof vis); while(Aug(S, INF));
} while(Upd());
return cost;
}
int main() {
scanf("%d%d", &n, &m);
S = 2*n*m; T = S + 1;
hsh['L'] = 3; hsh['R'] = 1; hsh['U'] = 2; hsh['D'] = 0;
for(int i = 0; i < n; ++ i) {
scanf("%s", mp[i]);
for(int j = 0; j < m; ++ j) {
Add(i*m+j, T, 0, 1);
Add(S, i*m+j+n*m, 0, 1);
for(int k = 0; k < 4; ++ k) {
int x = i + dd[k][0], y = j + dd[k][1];
if(x < 0) x = n-1;
if(x == n) x = 0;
if(y < 0) y = m-1;
if(y == m) y = 0;
Add(i*m+j+n*m, x*m+y, hsh[mp[i][j]] != k, 1);
}
}
}
printf("%d\n", ZKW());
}
BZOJ3171 Tjoi2013 循环格的更多相关文章
- bzoj3171: [Tjoi2013]循环格(费用流)
传送门 其实这题的建图并不难(虽然我并没有想出来) 首先,每一个点的入度和出度必须为$1$ 那么我们考虑拆点 每个点的出度点向它能到达的点的入度点连边,容量$1$,如果方向为原来的方向则费用$0$否则 ...
- Bzoj 3171: [Tjoi2013]循环格 费用流
3171: [Tjoi2013]循环格 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 741 Solved: 463[Submit][Status][ ...
- [Tjoi2013]循环格
[Tjoi2013]循环格 2014年3月18日1,7500 Description Input 第一行两个整数R,C.表示行和列,接下来R行,每行C个字符LRUD,表示左右上下. Output 一个 ...
- 洛谷 P3965 [TJOI2013]循环格 解题报告
P3965 [TJOI2013]循环格 题目背景 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子. 每个元素有一个坐标(行,列),其中左上角元素坐标为\((0,0)\).给定一个起始位\ ...
- BZOJ_3171_[Tjoi2013]循环格_最小费用最大流
BZOJ_3171_[Tjoi2013]循环格_最小费用最大流 Description 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为 ...
- [TJOI2013]循环格 费用流 BZOJ3171
题目背景 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0).给定一个起始位(r,c),你可以沿着箭头方向在格子间行走.即:如果 ...
- 【BZOJ3171】[TJOI2013] 循环格(网络流)
点此看题面 大致题意: 给你一个循环格,每个格子有一个方向.问你至少修改多少格子,才能使从每个格子出发都能回到原格子. 建图 这是道网络流题目,主要就是考虑如何建图. 我们可以把每个点拆成两个点,一个 ...
- 【bzoj3171】[Tjoi2013]循环格
题目描述: 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0).给定一个起始位置(r,c) ,你可以沿着箭头防线在格子间行走.即 ...
- bzoj 3171: [Tjoi2013]循环格
#include<cstdio> #include<iostream> #include<cstring> #define M 10000 #define inf ...
随机推荐
- java使用xsd校验xml样例
知识点:XSD文件是指XML结构定义 ( XML Schemas Definition )文件,是DTD的替代品.可以用一个指定的XML Schema来验证某个XML文档,以检查该XML文档是否符合其 ...
- WinServer2008R2 部署.NET4.0程序 注意事项
部署注意事项: 1.IIS应用程序池 集成模式 2.在web.config中的system.webServer下,添加 <modules runAllManagedModulesForA ...
- VC++ 动态生成 成组的 RadioButton 按钮组
先说一下 静态创建的方法: 单选按钮也属于CButton类,但由于单选按钮总是成组使用的,所以它在制作和使用上与普通按钮有一定区别.假设有三个单选按钮组成一组,初始时,第一个单选按钮处于选中状态.我们 ...
- 介绍开源的.net通信框架NetworkComms框架 源码分析(十五 ) CommsThreadPool自定义线程池
原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架 作者是英国人 以前是收费的 目前作者已经开源 许可是 ...
- NLPP-02-Exercises
<PYTHON自然语言处理>第2章 内容简介:各种文本语料库. 古腾堡项目 www.gutenberg.org OLAC元数据格式档 http://www.language-archive ...
- A 浪哥的烦恼 完全背包dp
https://biancheng.love/contest-ng/index.html#/131/problems 首先,去到n点的最小时间是所有数加起来. 然后,如果我1 --- 2,然后再2-- ...
- CF(协同过滤算法)
1 集体智慧和协同过滤 1.1 什么是集体智慧(社会计算)? 集体智慧 (Collective Intelligence) 并不是 Web2.0 时代特有的,只是在 Web2.0 时代,大家在 Web ...
- background-orgin属性
重点内容是:背景的显示范围是在元素的内边距之内的,如果要想改变显示范围,可以使用background-orgin和background-clip进行调整. (1)background-orgin有三个 ...
- Python全栈--9.1--面向对象进阶-super 类对象成员--类属性- 私有属性 查找源码类对象步骤 类特殊成员 isinstance issubclass 异常处理
上一篇文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中) 对象 ...
- 第三十九章 微服务CICD(1)- gitlab搭建与使用(docker版)
一.下载docker镜像 前提:docker引擎已经安装好. docker pull gitlab/gitlab-ce gitlab是8.13.1版本. 二.启动应用 docker run -d -h ...