洛谷 P2774 方格取数问题

简介: 题目背景 none! 题目描述 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。

题目背景

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\n",S-dinic());
    return 0;
}

 

目录
相关文章
|
1月前
lanqiao OJ 803 方格取数
lanqiao OJ 803 方格取数
19 3
|
1月前
lanqiaoOJ 211 剪格子
lanqiaoOJ 211 剪格子
13 3
|
6月前
【错题集-编程题】不相邻取数(动态规划 - 线性 dp)
【错题集-编程题】不相邻取数(动态规划 - 线性 dp)
|
6月前
|
人工智能 JavaScript
【错题集-编程题】最大子矩阵(二维前缀和)
【错题集-编程题】最大子矩阵(二维前缀和)
|
6月前
|
机器学习/深度学习 算法
P1004 方格取数
P1004 方格取数
|
人工智能 索引
洛谷P1005 [NOIP2007 提高组] 矩阵取数游戏
洛谷P1005 [NOIP2007 提高组] 矩阵取数游戏
|
机器学习/深度学习
1277:【例9.21】方格取数
1277:【例9.21】方格取数
每日三题-最大正方形 、完全平方数 、目标和
每日三题-最大正方形 、完全平方数 、目标和
87 2
每日三题-最大正方形 、完全平方数 、目标和
洛谷P3194 [HNOI2008]水平可见直线(计算几何+单调栈)
洛谷P3194 [HNOI2008]水平可见直线(计算几何+单调栈)
108 0
洛谷P3194 [HNOI2008]水平可见直线(计算几何+单调栈)