• 1907 方格取数 3


    1907 方格取数 3

     

     时间限制: 2 s
     空间限制: 256000 KB
     题目等级 : 大师 Master
     
     
    题目描述 Description

    «问题描述:
    在一个有m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任
    意2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。
    «编程任务:
    对于给定的方格棋盘,按照取数要求编程找出总和最大的数。

    输入描述 Input Description

    第1 行有2 个正整数m和n,分别表示棋盘的行数
    和列数。接下来的m行,每行有n个正整数,表示棋盘方格中的数。

    输出描述 Output Description

    将取数的最大总和输出

    样例输入 Sample Input

    3 3
    1 2 3
    3 2 3
    2 3 1

    样例输出 Sample Output

    11

    数据范围及提示 Data Size & Hint

    n,m<=30

    【题解】:最大点权独立集

    黑白染色,S到X集合中的点边容量为该点权值,Y到T同,不能同时取的两个格子连一条无穷大的边,结果是所有格子权值和减去最小割

    //同题:【tyvj1338】QQ农场

    #include<cstdio>
    #include<iostream>
    using namespace std;
    const int N=210,M=1e5+10;
    const int inf=0x3f3f3f3f;
    const int dx[]={0,0,1,-1};
    const int dy[]={1,-1,0,0};
    struct node{
        int v,next,cap;
    }e[M*10];int tot=1;
    int n,m,num,S,T,id[N][N],mp[N][N],head[M],dis[M],q[M*10];
    void add(int x,int y,int z){
        e[++tot].v=y;e[tot].cap=z;e[tot].next=head[x];head[x]=tot;
        e[++tot].v=x;e[tot].cap=0;e[tot].next=head[y];head[y]=tot;
    }
    bool inside(int x,int y){
        return x>0&&x<=n&&y>0&&y<=m;
    }
    bool bfs(){
        for(int i=S;i<=T;i++) dis[i]=inf;
        int h=0,t=1;q[t]=S;dis[S]=0;
        while(h!=t){
            int x=q[++h];
            for(int i=head[x];i;i=e[i].next){
                int v=e[i].v;
                if(e[i].cap&&dis[v]>dis[x]+1){
                    dis[v]=dis[x]+1;
                    if(v==T) return 1;
                    q[++t]=v;
                }
            }
        }
        return dis[T]<inf;
    }
    int dfs(int x,int f){
        if(x==T) return f;
        int used=0,t;
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].v;
            if(e[i].cap&&dis[v]==dis[x]+1){
                t=dfs(v,min(f,e[i].cap));
                e[i].cap-=t;e[i^1].cap+=t;
                used+=t;f-=t;
                if(!f) return used;
            }
        }
        dis[x]=0;
        return used;
    }
    int dinic(){
        int res=0;
        while(bfs()) res+=dfs(S,inf);
        return num-res;
    }
    void mapping(){
        int cnt=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                id[i][j]=++cnt;
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if((i+j)&1^1){
                    add(S,id[i][j],mp[i][j]);
                    for(int k=0;k<4;k++){
                        int nx=i+dx[k],ny=j+dy[k];
                        if(inside(nx,ny)) add(id[i][j],id[nx][ny],inf);
                    }
                }
                else add(id[i][j],T,mp[i][j]);
            }
        }
    }
    int main(){
        scanf("%d%d",&n,&m);S=0;T=n*m+1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&mp[i][j]);num+=mp[i][j];
            }
        }
        mapping();
        printf("%d",dinic());
        return 0;
    }
  • 相关阅读:
    全网最贴心webpack系列教程和配套代码
    webpack4 系列教程(十五):开发模式与webpack-dev-server
    CSS元素显示模式
    CSS符合选择器
    Emmet语法
    CSS引入方式
    CSS文本属性
    CSS字体属性
    CSS语法规范一
    案例
  • 原文地址:https://www.cnblogs.com/shenben/p/6260496.html
Copyright © 2020-2023  润新知