• 洛谷 P2045 方格取数加强版


    题目描述

    给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格子的数取出来,该格子的数就变成0,这样一共走K次,现在要求K次所达到的方格的数的和最大

    输入格式

    第一行两个数n,k(1<=n<=50, 0<=k<=10)

    接下来n行,每行n个数,分别表示矩阵的每个格子的数

    输出格式

    一个数,为最大和

    输入输出样例

    输入 #1
    3 1
    1 2 3
    0 2 1
    1 4 2
    输出 #1
    11

    说明/提示

    每个格子中的数不超过1000

    思路:一道比较好的费用流题目。道理还是比较容易想的,但是我还是想了很长时间。。。

    我个人的做法是这样的,对于一个格子,我们把它拆成4个点,分成:一个入点,一个出点,和两个中间点,入点到一个中间点连一条容量为1,边权为当前格子权值的边,到另一个中间点连一条容量为K-1,边权为0的边,两个中间点再向出点连各自的边,容量分别为1和K-1(均为inf也可以),边权均为0;

    对于每一个出点,向右方向和下方向的格子的入点连容量为K,边权为0的边。最后源点和汇点分别向(1,1)(n,n)连边。

    PS:我的做法其实过于麻烦,事实上只要拆成2个点即可。无需在拆中间点。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<queue>
      6 using namespace std;
      7 const int N = 2e4 + 5;
      8 const int M = 1e5 + 5;
      9 struct edge{
     10     int from, to, cap, dis;
     11 }e[M << 1];
     12 int head[N], nxt[M << 1], tot = 1;
     13 void adde(int f, int t, int c, int d)
     14 {
     15     e[++ tot] = (edge){f, t, c, d};
     16     nxt[tot] = head[f];
     17     head[f] = tot;
     18 }
     19 int n, st, ed;
     20 const int inf = 0x3f3f3f3f;
     21 int dist[N], inq[N], pre[N];
     22 queue <int> Q;
     23 bool spfa()
     24 {
     25     memset(dist, 0x3f, sizeof dist);
     26     memset(inq, 0, sizeof inq);
     27     memset(pre, 0, sizeof pre);
     28     while(!Q.empty()) Q.pop();
     29     dist[st] = 0;
     30     inq[st] = 1;
     31     Q.push(st);
     32     while(!Q.empty())
     33     {
     34         int u = Q.front();
     35         Q.pop();
     36         inq[u] = 0;
     37         for(int i = head[u]; i; i = nxt[i])
     38         {
     39             int v = e[i].to;
     40             if(dist[v] > dist[u] + e[i].dis && e[i].cap)
     41             {
     42                 dist[v] = dist[u] + e[i].dis;
     43                 pre[v] = i;
     44                 if(!inq[v])
     45                 {
     46                     inq[v] = 1;
     47                     Q.push(v);
     48                 }
     49             }
     50         }
     51     }
     52     return (dist[ed] != inf);
     53 }
     54 int cost = 0;
     55 void redate()
     56 {
     57     int fl = inf;
     58     for(int i = pre[ed]; i; i = pre[e[i].from]) fl = min(fl, e[i].cap);
     59     for(int i = pre[ed]; i; i = pre[e[i].from])
     60     {
     61         e[i].cap -= fl;
     62         e[i^1].cap += fl;
     63         cost += fl * e[i].dis;
     64     }
     65 }
     66 void mcmf()
     67 {
     68     while(spfa()) redate();
     69 }
     70 int K;
     71 int num[N];
     72 void solve()
     73 {
     74     st = 0, ed = 5*n*n;
     75     adde(st, 1, K, 0);
     76     adde(1, st, 0, 0);
     77     adde(4*n*n, ed, K, 0);
     78     adde(ed, 4*n*n, 0, 0);
     79     for(int i = 1; i <= n*n; i ++)
     80     {
     81         adde(i, i + n*n, 1, -num[i]);
     82         adde(i + n*n, i, 0, num[i]);//(1,2
     83         adde(i, i + 2*n*n, K - 1, 0);
     84         adde(i + 2*n*n, i, 0, 0);//(1,3
     85         adde(i + n*n, i + 3*n*n, 1, 0);
     86         adde(i + 3*n*n, i + n*n, 0, 0);//(2,4
     87         adde(i + 2*n*n, i + 3*n*n, K - 1, 0);
     88         adde(i + 3*n*n, i + 2*n*n, 0, 0);//(3,4
     89     }
     90     for(int i = 1; i <= n*n; i ++)
     91     {
     92         if(i % n)
     93         {
     94             adde(i + 3*n*n, i + 1, K, 0);
     95             adde(i + 1, i + 3*n*n, 0, 0);
     96         }
     97         if(i <= n*(n - 1))
     98         {
     99             adde(i + 3*n*n, i + n, K, 0);
    100             adde(i + n, i + 3*n*n, 0, 0);
    101         }
    102     }
    103 }
    104 int main()
    105 {
    106     scanf("%d%d", &n, &K);
    107     for(int i = 1; i <= n; i ++)
    108         for(int j = 1; j <= n; j ++)
    109             scanf("%d", &num[j + (i - 1)*n]);
    110     solve();
    111     mcmf();
    112     printf("%d
    ", -cost);
    113     return 0;
    114 }
  • 相关阅读:
    <input type='date'>传到后台怎么接收
    @Conditionnal注解和拦截器
    docker安装nginx
    vue npm run build报错 npm ERR! missing script: build
    阳哥讲面试题(七)Redis五种基本类型,分布式锁
    阳哥讲面试题(六)AOP,循环依赖
    mysql建表报错(this is incompatible with sql_mode=only_full_group_by)
    阳哥讲面试题(五)各种锁,LockSupport,AQS
    SSM_CRUD新手练习(2)配置文件
    Mysql逻辑分层、存储引擎
  • 原文地址:https://www.cnblogs.com/loi-frank/p/11650084.html
Copyright © 2020-2023  润新知