zoukankan      html  css  js  c++  java
  • 洛谷 P2774 方格取数问题

    题目背景

    none!

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

    程序运行结束时,将取数的最大总和输出

    输入输出样例

    输入样例#1:
    3 3
    1 2 3
    3 2 3
    2 3 1 
    输出样例#1:
    11

    说明

    none!

    解题思路

      一道和骑士共存问题差不多的题目,二分图黑白染色后跑最大独立集,这里每个白格向四周连边,而不是马能攻击到的地方(废话)。

    源代码

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    
    int n,m;
    int a[1000][1000]={0};
    int S=0;
    inline int id(int x,int y)
    {
        return (x-1)*m+y;
    }
    
    int s,t;
    struct Edge{
        int next,to,flow;
    }e[1000010];
    int cnt=2,head[1000]={0};
    void add(int u,int v,int f)
    {
        e[cnt]={head[u],v,f};
        head[u]=cnt++;
        e[cnt]={head[v],u,0};
        head[v]=cnt++;
    }
    
    
    int dis[1000]={0};
    bool bfs()
    {
        memset(dis,0,sizeof(dis));
        std::queue<int> q;
        q.push(s);
        dis[s]=1;
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int i=head[u];i;i=e[i].next)
            {
                int v=e[i].to;
                if(dis[v]||!e[i].flow) continue;
                dis[v]=dis[u]+1;
                q.push(v);
            }
        }
        return dis[t]!=0;
    }
    
    int dfs(int u,int f)
    {
        if(u==t||f==0) return f;
        int flow_sum=0;
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(dis[v]!=dis[u]+1||!e[i].flow) continue;
            int temp=dfs(v,std::min(e[i].flow,f-flow_sum));
            e[i].flow-=temp;
            e[i^1].flow+=temp;
            flow_sum+=temp;
            if(flow_sum>=f) break;
        }
        if(!flow_sum) dis[u]=-1;
        return flow_sum;
    }
    
    int dinic()
    {
        int ans=0;
        while(bfs())
        {
            while(int temp=dfs(s,0x7fffffff))
                ans+=temp;
        }
        return ans;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        s=n*m+1,t=s+1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&a[i][j]),S+=a[i][j];
        int bh[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if((i+j)&1)
                {
                    add(s,id(i,j),a[i][j]);
                    for(int k=0;k<4;k++)
                    {
                        int x=i+bh[k][0],y=j+bh[k][1];
                        if(x>=1&&x<=n&&y>=1&&y<=m)
                            add(id(i,j),id(x,y),0x7fffffff);
                    }
                }
                else
                    add(id(i,j),t,a[i][j]);
            }
        }
        printf("%d
    ",S-dinic());
        return 0;
    }
  • 相关阅读:
    02注册Github账户
    软件工程概论第一节
    01课堂测试
    第二阶段冲刺01
    在子类中,若要调用父类中被覆盖的方法,可以使用super关键字
    动手动脑
    springBoot学习 错误记录
    什么是Hadoop?什么是HDFS?
    springCloud当中Eureca sever当中Camden到底是什么?
    Eureca Server的Helloworld例子
  • 原文地址:https://www.cnblogs.com/wawcac-blog/p/7100850.html
Copyright © 2011-2022 走看看