• 1227 方格取数 2


    题目描述

    给出一个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

    说明

    每个格子中的数不超过100

    【题解】

    先把每个点拆成2个A,B,
    Ai->Bi之间连2条边,一条流量为1,费用为该格点上的权值,以计算费用,
    另一条流量为INF,费用为0,保证通路,再把每个点扫一遍,
    可以到达的点之间Bi->Aj连流量INF,费用0的边。
    虚拟源st=0,st->A1(第一个点)连费用0,流量k的边,限制流量。
    虚拟汇ed=n*n*2+1,,右下角的格点Bi->ed连费用0,流量k的边。。。
    跑一遍最大费用最大流就行了。。

    #include<cstdio>
    #include<iostream>
    using namespace std;
    const int N=110;
    const int M=N*N;
    const int inf=0x3f3f3f3f;
    struct node{
        int v,next,cap,cost;
    }e[M*50];int tot=1;
    int n,m,k,S,T,ans,head[M],dis[M],pree[M],q[M*50];
    bool vis[M];
    void add(int x,int y,int cap,int cost){
        e[++tot].v=y;e[tot].cap=cap;e[tot].cost=cost;e[tot].next=head[x];head[x]=tot;
        e[++tot].v=x;e[tot].cap=0;e[tot].cost=-cost;e[tot].next=head[y];head[y]=tot;
    }
    bool spfa(){
        for(int i=S;i<=T;i++) vis[i]=0,dis[i]=-inf;
        int h=0,t=1;
        q[t]=S;dis[S]=0;vis[S]=1;
        while(h!=t){
            int x=q[++h];vis[x]=0;
            for(int i=head[x];i;i=e[i].next){
                int v=e[i].v;
                if(e[i].cap>0&&dis[v]<dis[x]+e[i].cost){
                    dis[v]=dis[x]+e[i].cost;
                    pree[v]=i;
                    if(!vis[v]){
                        vis[v]=1;
                        q[++t]=v;
                    }
                }
            }
        }
        return dis[T]>0;
    }
    void augment(){
        int tmp=inf;
        for(int i=T;i!=S;i=e[pree[i]^1].v){
            tmp=min(tmp,e[pree[i]].cap);
        }
        for(int i=T;i!=S;i=e[pree[i]^1].v){
            ans+=tmp*e[pree[i]].cost;
            e[pree[i]].cap-=tmp;
            e[pree[i]^1].cap+=tmp;
        }
    }
    int main(){
        scanf("%d%d",&n,&k);S=0;T=n*n*2+1;
        for(int i=1,now=1,plus=n*n,x;i<=n;i++){
            for(int j=1;j<=n;j++,now++){
                scanf("%d",&x);
                add(now,now+plus,1,x);
                add(now,now+plus,inf,0);
                if(j<n) add(now+plus,now+1,inf,0);
                if(i<n) add(now+plus,now+n,inf,0);
            }
        }
        add(S,S+1,k,0);
        add(T-1,T,k,0);
        while(spfa()) augment();
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    Kafka常用操作备忘
    Spark执行流程(转)
    Spark性能优化总结
    Kafka学习笔记
    vue-简单例子初始化
    解析字符串模板函数
    js的apply 和 call区别
    水平垂直居中
    IE8 div旋转 Matrix,模拟轮播前后翻页按钮
    jsp 自定义标签-SimpleTagSupport 使用笔记
  • 原文地址:https://www.cnblogs.com/shenben/p/6260353.html
Copyright © 2020-2023  润新知