zoukankan      html  css  js  c++  java
  • 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

    思路

    拆点+最大流费用最大流

    代码

    #include<bits/stdc++.h>
    #define N 107000
    #define M 107000
    #define inf 1<<29
    using namespace std;
    struct node{
        int y,z,p,next;
    }e[M*2];
    int tot=1,head[N],maxflow=0,ans=0,s,t;
    void add(int x,int y,int z,int p){
        e[++tot].y=y;e[tot].z=z;e[tot].p=p;
        e[tot].next=head[x];head[x]=tot;
    }
    int incf[N],v[N],pre[N],d[N];
    bool spfa(){
        queue<int> q;
        memset(d,0xcf,sizeof(d));
        memset(v,0,sizeof(v));
        q.push(s);d[s]=0;v[s]=1;
        incf[s]=inf;
        while(q.size()){
            int x=q.front();v[x]=0;q.pop();
            for(int i=head[x];i;i=e[i].next){
                int y=e[i].y,z=e[i].z;
                if(!z) continue;
                if(d[y]<d[x]+e[i].p){
                    d[y]=d[x]+e[i].p;
                    incf[y]=min(incf[x],z);
                    pre[y]=i;
                    if(!v[y]) v[y]=1,q.push(y);
                }
            }
        }
        if(d[t]==0xcfcfcfcf) return false;
        return true;
    }
    void update(){
        int x=t;
        while(x!=s){
            int i=pre[x];
            e[i].z-=incf[t];
            e[i^1].z+=incf[t];
            x=e[i^1].y; 
        }
        maxflow+=incf[t];
        ans+=d[t]*incf[t];
    }
    int gcd(int a,int b){
        return b==0?a:gcd(b,a%b);
    }
    int f(int x,int y){
        int k=x*x-y*y;
        int g=sqrt(k);
        if(g*g==k&&gcd(y,g)==1) return 1;
        else return 0;
    }
    int n,k;
    int num(int a,int b){
        return (a-1)*n+b;
    }
    int a[60][60];
    #define MAXN 3000
    int main(){
        cin>>n>>k;
        s=num(1,1);t=num(n,n)+MAXN;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&a[i][j]);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                add(num(i,j),num(i,j)+MAXN,1,a[i][j]);add(num(i,j)+MAXN,num(i,j),0,-a[i][j]);
                add(num(i,j),num(i,j)+MAXN,k-1,0); add(num(i,j)+MAXN,num(i,j),0,0);
                if (i+1<=n) add(num(i,j)+MAXN,num(i+1,j),k,0),add(num(i+1,j),num(i,j)+MAXN,0,0);
                if (j+1<=n) add(num(i,j)+MAXN,num(i,j+1),k,0),add(num(i,j+1),num(i,j)+MAXN,0,0);
            }
        }
        while(spfa()) 
            update();
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    MQ、JMS以及ActiveMQ 关系的理解
    java对象 深度克隆(不实现Cloneable接口)和浅度克隆
    crontab 各参数详解及如何查看日志记录
    mybatis xml 文件中like模糊查询
    jexl2 执行字符串Java代码
    java代码执行字符串中的逻辑运算方法
    mybatis 传入多个参数
    mybatis通用mapper源码解析(二)
    mybatis通用mapper源码解析(一)
    mybatise插件反向生成数据库表相关Java代码
  • 原文地址:https://www.cnblogs.com/wangyiding2003/p/11530368.html
Copyright © 2011-2022 走看看