• 方格取数3


     方格取数 3

     时间限制: 2 s
     空间限制: 256000 KB
     
     
     
    题目描述 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


    最小割。由于题目要求不能选择相邻的两个数,我们可以考虑给棋盘染色,白格子只与黑格子相邻,反之亦然。源点都和某一种颜色的格子相连,汇点和另一种颜色的格子相连,权值为格子里的数。相邻两个格子之间建一条流量为无穷大的边,这样就保证最小割只会选择去除与源点或汇点相邻的边,而去除这条边就意味着不选这个格子里的数。最后当最小割选择完成后,源点和汇点没有路径相连,这就意味着没有相邻的格子被同时保留。(因为源点和汇点连接必须要经过相邻格子之间的边,而现在源点和汇点不相连,就意味着一旦某一个格子被选择,它周围的格子都不能再被选择了)。
    #include<bits/stdc++.h>
    #define N 1000
    using namespace std;
    
    long long tot=0;
    typedef struct{long long v,flow;}ss;
    vector<long long>edges[N];
    ss edg[N*N];
    long long dis[N];
    long long S,T;
    long long current[N];
    
    void addedge(long long u,long long v,long long flow)
    {
        edg[tot]=(ss){v,flow};
        edges[u].push_back(tot++);
        edg[tot]=(ss){u,0};
        edges[v].push_back(tot++);
    }
    
    bool bfs()
    {
        queue<long long>q;
        q.push(S);
        for(long long i=0;i<N;i++)dis[i]=LLONG_MAX/2;
        dis[S]=1;
    
        while(!q.empty())
        {
            int now=q.front();
            q.pop();
            long long Size=edges[now].size();
    
            for(long long i=0;i<Size;i++)
            {
                ss &e=edg[edges[now][i]];
    
                if(e.flow>0&&dis[e.v]==LLONG_MAX/2)
                {
                    dis[e.v]=dis[now]+1;
                    q.push(e.v);
                }
            }
        }
    
        if(dis[T]==LLONG_MAX/2)return 0;
        return 1;
    }
    
    long long dfs(long long x,long long flow)
    {
        if(x==T)return flow;
    
        long long Size=edges[x].size();
        for(long long i=current[x];i<Size;i++)
        {
            current[x]=i;
            ss &e=edg[edges[x][i]];
            if(dis[x]+1==dis[e.v]&&e.flow>0)
            {
                long long Flow=dfs(e.v,min(flow,(long long)e.flow));
                if(Flow!=0)
                {
                    e.flow-=Flow;
                    edg[edges[x][i]^1].flow+=Flow;
                    return Flow;
                }
            }
    
        }
        return 0;
    
    }
    long long dinic()
    {
        long long ans=0;
        while(bfs())
        {
            memset(current,0,sizeof(current));
            long long flow;
            while(flow=dfs(S,LLONG_MAX))ans+=flow;
        }
        return ans;
    }
    
    
    int main()
    {
        int m,n,t=0;
        int Map[35][35];
        int num[35][35];
    
        long long ans=0;
    
        scanf("%d %d",&m,&n);
        for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&Map[i][j]);
            num[i][j]=t++;
            ans+=Map[i][j];
    
        }
    
        S=t++;
        T=t++;
    
        for(int i=1;i<=m;i++)
        {
            for(int j=(i+1)%2+1;j<=n;j+=2)
            {
                addedge(S,num[i][j],Map[i][j]);
    
                if(i-1>=1)addedge(num[i][j],num[i-1][j],LLONG_MAX/2);
                if(i+1<=m)addedge(num[i][j],num[i+1][j],LLONG_MAX/2);
                if(j-1>=1)addedge(num[i][j],num[i][j-1],LLONG_MAX/2);
                if(j+1<=n)addedge(num[i][j],num[i][j+1],LLONG_MAX/2);
    
            }
    
        }
    
        for(int i=1;i<=m;i++)
        {
            for(int j=i%2+1;j<=n;j+=2)
            {
                addedge(num[i][j],T,Map[i][j]);
            }
        }
    
    
        printf("%lld",ans-dinic());
        return 0;
    }
    View Code
  • 相关阅读:
    C++ 不用 < > 与 : ?运算符判断 a,b大小
    CentOS7 MariaDB10
    CentOS Linux 挂载NTFS
    Linux访问Windows共享
    Emacs配置与插件集记录
    驱动精妙耍流氓,强制安装"新毒霸"
    C# TextBox控件之大小写自动转换
    生活随笔
    显示外网IP
    MySql
  • 原文地址:https://www.cnblogs.com/tian-luo/p/9501571.html
Copyright © 2020-2023  润新知