传送门

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。跑一次费用流,答案就是费用了。

  1. /**************************************************************
  2. Problem: 3171
  3. User: geng4512
  4. Language: C++
  5. Result: Accepted
  6. Time:4 ms
  7. Memory:1236 kb
  8. ****************************************************************/
  9. #include<algorithm>
  10. #include<cstdio>
  11. #include<cstring>
  12. #define INF 0x3f3f3f3f
  13. #define MAXN 10005
  14. using namespace std;
  15. int n, m, S, T, dd[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
  16. char mp[30][30];
  17. int hsh[200];
  18. struct Node { int v, w, f, nxt; } e[MAXN<<1];
  19. int Adj[MAXN], ecnt = 1, cost, dis[MAXN];
  20. int vis[MAXN];
  21. inline void Add(int u, int v, int w, int f) {
  22. ++ ecnt; e[ecnt].v = v; e[ecnt].w = w; e[ecnt].f = f; e[ecnt].nxt = Adj[u]; Adj[u] = ecnt;
  23. ++ ecnt; e[ecnt].v = u; e[ecnt].w = -w; e[ecnt].f = 0; e[ecnt].nxt = Adj[v]; Adj[v] = ecnt;
  24. }
  25. bool Upd() {
  26. int tmp = INF;
  27. for(int u = 0; u <= T; ++ u) if(vis[u])
  28. for(int i = Adj[u]; i; i = e[i].nxt)
  29. if(!vis[e[i].v] && e[i].f)
  30. tmp = min(tmp, dis[e[i].v] + e[i].w - dis[u]);
  31. if(tmp == INF) return 0;
  32. for(int u = 0; u <= T; ++ u) if(vis[u]) dis[u] += tmp;
  33. return 1;
  34. }
  35. int Aug(int u, int augco) {
  36. if(u == T) {
  37. cost += dis[S] * augco;
  38. return augco;
  39. }
  40. int augc = augco, delta, v;
  41. vis[u] = 1;
  42. for(int i = Adj[u]; i; i = e[i].nxt) {
  43. v = e[i].v;
  44. if(e[i].f && !vis[v] && dis[u] - e[i].w == dis[v]) {
  45. delta = Aug(v, min(e[i].f, augc));
  46. augc -= delta; e[i].f -= delta; e[i^1].f += delta;
  47. if(!augc) return augco;
  48. }
  49. }
  50. return augco - augc;
  51. }
  52. int ZKW() {
  53. do {
  54. do memset(vis, 0, sizeof vis); while(Aug(S, INF));
  55. } while(Upd());
  56. return cost;
  57. }
  58. int main() {
  59. scanf("%d%d", &n, &m);
  60. S = 2*n*m; T = S + 1;
  61. hsh['L'] = 3; hsh['R'] = 1; hsh['U'] = 2; hsh['D'] = 0;
  62. for(int i = 0; i < n; ++ i) {
  63. scanf("%s", mp[i]);
  64. for(int j = 0; j < m; ++ j) {
  65. Add(i*m+j, T, 0, 1);
  66. Add(S, i*m+j+n*m, 0, 1);
  67. for(int k = 0; k < 4; ++ k) {
  68. int x = i + dd[k][0], y = j + dd[k][1];
  69. if(x < 0) x = n-1;
  70. if(x == n) x = 0;
  71. if(y < 0) y = m-1;
  72. if(y == m) y = 0;
  73. Add(i*m+j+n*m, x*m+y, hsh[mp[i][j]] != k, 1);
  74. }
  75. }
  76. }
  77. printf("%d\n", ZKW());
  78. }
  79. 

BZOJ3171 Tjoi2013 循环格的更多相关文章

  1. bzoj3171: [Tjoi2013]循环格(费用流)

    传送门 其实这题的建图并不难(虽然我并没有想出来) 首先,每一个点的入度和出度必须为$1$ 那么我们考虑拆点 每个点的出度点向它能到达的点的入度点连边,容量$1$,如果方向为原来的方向则费用$0$否则 ...

  2. Bzoj 3171: [Tjoi2013]循环格 费用流

    3171: [Tjoi2013]循环格 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 741  Solved: 463[Submit][Status][ ...

  3. [Tjoi2013]循环格

    [Tjoi2013]循环格 2014年3月18日1,7500 Description Input 第一行两个整数R,C.表示行和列,接下来R行,每行C个字符LRUD,表示左右上下. Output 一个 ...

  4. 洛谷 P3965 [TJOI2013]循环格 解题报告

    P3965 [TJOI2013]循环格 题目背景 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子. 每个元素有一个坐标(行,列),其中左上角元素坐标为\((0,0)\).给定一个起始位\ ...

  5. BZOJ_3171_[Tjoi2013]循环格_最小费用最大流

    BZOJ_3171_[Tjoi2013]循环格_最小费用最大流 Description 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为 ...

  6. [TJOI2013]循环格 费用流 BZOJ3171

    题目背景 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0).给定一个起始位(r,c),你可以沿着箭头方向在格子间行走.即:如果 ...

  7. 【BZOJ3171】[TJOI2013] 循环格(网络流)

    点此看题面 大致题意: 给你一个循环格,每个格子有一个方向.问你至少修改多少格子,才能使从每个格子出发都能回到原格子. 建图 这是道网络流题目,主要就是考虑如何建图. 我们可以把每个点拆成两个点,一个 ...

  8. 【bzoj3171】[Tjoi2013]循环格

    题目描述: 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0).给定一个起始位置(r,c) ,你可以沿着箭头防线在格子间行走.即 ...

  9. bzoj 3171: [Tjoi2013]循环格

    #include<cstdio> #include<iostream> #include<cstring> #define M 10000 #define inf ...

随机推荐

  1. Linux VM acquisition

    The evidence is a VM as below. The flat vmdk is the real disk, and the vmdk only 1kb is just a descr ...

  2. mongodb账号安全操作

    安装服务 mongod --install --serviceName mongodb --storageEngine=mmapv1 --dbpath i:\mongodb\data --journa ...

  3. weed-fs 压力测试

    阅读<Weed-FS/杂草文件系统 小文件存储集群 安装 使用 测试>中提到weedfs的负载压力不是很好,在看过代码后进行了相应测试,未发现负载压力有何问题.   weedfs mast ...

  4. 如何进行服务器的批量管理以及python 的paramiko的模块

    最近对公司的通道机账号进行改造管理,全面的更加深入的理解了公司账号管理的架构.(注:基本上所有的机器上的ssh不能使用,只有部分机器能够使用.为了安全的角度考虑,安装的不是公版的ssh,而都是定制版的 ...

  5. 多媒体(4):JPEG图像压缩编码

    (重要的事放前面)此JPEG的C++实现见 https://github.com/chencjGene/SoftEngineering/tree/master/JPEG 目录 多媒体(1):MCI接口 ...

  6. call_user_func函数

    <?php function funa($b,$c) { echo $b; echo $c; } call_user_func('funa', "111","222 ...

  7. Echarts tooltip文字没有左对齐

    tooltip : { trigger: 'axis', axisPointer : { // 坐标轴指示器,坐标轴触发有效 type : 'shadow' // 默认为直线,可选为:'line' | ...

  8. E. Santa Claus and Tangerines 二分答案 + 记忆化搜索

    http://codeforces.com/contest/752/problem/E 首先有一个东西就是,如果我要检测5,那么14我们认为它能产生2个5. 14 = 7 + 7.但是按照平均分的话, ...

  9. 第1章 C#类型基础

    1.1值类型和引用类型 1.1.1 值类型 使用值类型之前需要对值类型的所有元素初始化(普通值类型和结构体). 结构还有一个特性:调用结构上的方法前,需要对其所有的字段进行赋值,为了避免对结构体中所有 ...

  10. Dijkstra 最短路算法(只能计算出一条最短路径,所有路径用dfs)

    上周我们介绍了神奇的只有五行的 Floyd 最短路算法,它可以方便的求得任意两点的最短路径,这称为"多源最短路".本周来来介绍指定一个点(源点)到其余各个顶点的最短路径,也叫做&q ...