zoukankan      html  css  js  c++  java
  • codevs 1227 方格取数 2

    Description

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

    Input Description

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

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

    Output Description

    一个数,为最大和

    Sample Input

    3 1

    1 2 3

    0 2 1

    1 4 2

    Sample Output

    11

    Data Size & Hint

    1<=n<=50, 0<=k<=10

        恩......说实话这道题应该是网络流的题,但是想了半天也没有想出来......膜了网上的题解后才发现,这是道费用流的题(亏我一直在想怎么控制和最大)

        知道这是费用流的以后就很好办了。由于每个点可能有两种情况,即之前没经过这个点时走到这个点,和之前已经走过这个点了。前一种情况需要计算贡献,而后一种情况则不需要。

        然后,我们考虑如何控制这两种情况。我们可以将每个点x拆开,拆为x1与x2。这样每次从x1走到x2时就可以把这个点的贡献给算进去。由于前一种情况只有一次,而后一种情况最多有k-1次,所以我们在x1与x2之间连两种边,一种容量为1,费用为这个节点的值(对应第一种情况),另一种容量为k-1,费用为0(对应第二种情况)。然后考虑这个点往下和往右连边,假设这两个点分别为y,z,那么从x2往y1、z1分别连一条容量为k,费用为0的边即可(自己想一想,不难的)。然后跑一遍最大费用最大流即可。

        代码如下:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
     7 #define maxn 100010
     8 #define INF (1<<28)
     9 #define r(j) (j^1)
    10 
    11 using namespace std;
    12 typedef long long llg;
    13 
    14 int head[maxn],to[maxn],next[maxn],c[maxn],f[maxn],ff[maxn];
    15 int n,k,tt=1,ans,dis[maxn],d[maxn],fa[maxn],d2[maxn],l,r,hui;
    16 bool w[maxn];
    17 
    18 void link(int x,int y,int z,int o){
    19     to[++tt]=y;next[tt]=head[x];head[x]=tt;
    20     to[++tt]=x;next[tt]=head[y];head[y]=tt;
    21     c[tt-1]=z; f[tt-1]=o; f[tt]=-o;
    22 }
    23 
    24 bool spfa(){
    25     for(int i=1;i<=hui;i++) dis[i]=-1,d2[i]=INF;
    26     dis[1]=0; l=r=0; d[r++]=1; w[1]=1;
    27     while(l!=r){
    28         int u=d[l++]; l%=maxn; w[u]=0;
    29         for(int i=head[u],v;v=to[i],i;i=next[i])
    30             if(c[i]>0 && dis[v]<dis[u]+f[i]){
    31                 dis[v]=dis[u]+f[i];
    32                 d2[v]=min(d2[u],c[i]);
    33                 fa[v]=u; ff[v]=i;
    34                 if(!w[v]){
    35                     w[v]=1;d[r++]=v;
    36                     r%=maxn;
    37                 }
    38             }
    39     }
    40     if(dis[hui]==-1) return 0;
    41     ans+=dis[hui]*d2[hui];
    42     int now=hui;
    43     while(now!=1){
    44         c[ff[now]]-=d2[hui];
    45         c[r(ff[now])]+=d2[hui];
    46         now=fa[now];
    47     }
    48     return 1;
    49 }
    50 
    51 int main(){
    52     File("a");
    53     scanf("%d%d",&n,&k);hui=n*n<<1;
    54     for(int i=1,now=1,x;i<=n;i++)
    55         for(int j=1;j<=n;j++,now++){
    56             scanf("%d",&x);
    57             link(now,now+n*n,1,x); link(now,now+n*n,k-1,0);
    58             if(j<n) link(now+n*n,now+1,k,0);
    59             if(i<n) link(now+n*n,now+n,k,0);
    60         }
    61     while(spfa());
    62     printf("%d",ans);
    63     return 0;
    64 }
  • 相关阅读:
    Matplotlib如何绘制子图
    数据挖掘的葵花宝典
    Matplotlib如何显示中文
    python绘制WordCloud词云图
    Selenium实现微博自动化运营:关注、点赞、评论
    从小白视角理解<数据挖掘十大算法>
    Laravel模型自动转换类型
    python数据分析常用图大集合
    数据分析常见概念
    Pandas数据分析基础之时间序列
  • 原文地址:https://www.cnblogs.com/lcf-2000/p/5567608.html
Copyright © 2011-2022 走看看