[HDU 1565+1569] 方格取数

HDU 1565

方格取数(1)

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5961    Accepted Submission(s): 2268


Problem Description
给你一个n*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。
 
Input
包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数(n<=20)
 
Output
对于每个测试实例,输出可能取得的最大的和
  
Sample Input
3 75 15 21 75 15 28 34 70 5
 
Sample Output
188
 
最大点权独立集
弱弱的EK算法
邻接矩阵实现 124MS
邻接表实现 15MS
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <set>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
#define INF 0x3f3f3f3f
#define ll long long
#define N 510

int n;
int src;
int des;
int sum;
int pre[N];
int mpt[N][N];
int map[N][N];
int dir[4][2]={1,0,-1,0,0,1,0,-1};
queue<int> q;

bool bfs()
{
    while(!q.empty()) q.pop();
    memset(pre,-1,sizeof(pre));
    pre[src]=0;
    q.push(src);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int v=0;v<=n*n+1;v++)
        {
            if(pre[v]==-1 && mpt[u][v]>0)
            {
                pre[v]=u;
                if(v==des) return 1;
                q.push(v);
            }
        }
    }
    return 0;
}
int EK()
{
    int maxflow=0;
    while(bfs())
    {
        int minflow=INF;
        for(int i=des;i!=src;i=pre[i])
            minflow=min(minflow,mpt[pre[i]][i]);
        maxflow+=minflow;
        for(int i=des;i!=src;i=pre[i])
        {
            mpt[pre[i]][i]-=minflow;
            mpt[i][pre[i]]+=minflow;
        }
    }
    return maxflow;
}
int main()
{
    int i,j,k;
    while(scanf("%d",&n)!=EOF)
    {
        sum=0;
        memset(mpt,0,sizeof(mpt));
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                scanf("%d",&map[i][j]);
                sum+=map[i][j];
            }
        }
        src=0;
        des=n*n+1;
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                if((i+j)%2==0) mpt[src][(i-1)*n+j]=map[i][j];
                else mpt[(i-1)*n+j][des]=map[i][j];
            }
        }
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                if((i+j)%2==0)
                {
                    for(k=0;k<4;k++)
                    {
                        int x=i+dir[k][0];
                        int y=j+dir[k][1];
                        if(x>=1 && x<=n && y>=1 && y<=n)
                        {
                            mpt[(i-1)*n+j][(x-1)*n+y]=INF;
                        }
                    }
                }
            }
        }
        printf("%d
",sum-EK());
    }
    return 0;
}

HDU 1569

和方格取数1数据大小不一样,用上面的会超时,可能是写搓了。

邻接表实现 280ms

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <set>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
#define INF 0x3f3f3f3f
#define ll long long
#define N 20510

struct Edge
{
    int to,next,val;
}edge[N];
int tot;
int head[N];

int n;
int m;
int src;
int des;
int sum;
int pre[N];
int path[N];
int map[N][N];
int dir[4][2]={1,0,-1,0,0,1,0,-1};
queue<int> q;

void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
}
void add(int u,int v,int w)
{
    edge[tot].to=v;
    edge[tot].val=w;
    edge[tot].next=head[u];
    head[u]=tot++;

    edge[tot].to=u;
    edge[tot].val=0;
    edge[tot].next=head[v];
    head[v]=tot++;

}
bool bfs()
{
    while(!q.empty()) q.pop();
    memset(pre,-1,sizeof(pre));
    pre[src]=0;
    q.push(src);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(pre[v]==-1 && edge[i].val>0)
            {
                pre[v]=u;
                path[v]=i;
                if(v==des) return 1;
                q.push(v);
            }
        }
    }
    return 0;
}
int EK()
{
    int maxflow=0;
    while(bfs())
    {
        int minflow=INF;
        for(int i=des;i!=src;i=pre[i])
            minflow=min(minflow,edge[path[i]].val);
        maxflow+=minflow;
        for(int i=des;i!=src;i=pre[i])
        {
            edge[path[i]].val-=minflow;
            edge[path[i]^1].val+=minflow;
        }
    }
    return maxflow;
}
int main()
{
    int i,j,k;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        sum=0;
        init();
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                scanf("%d",&map[i][j]);
                sum+=map[i][j];
            }
        }
        src=0;
        des=n*m+1;
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                if((i+j)%2==0) add(src,(i-1)*m+j,map[i][j]);
                else add((i-1)*m+j,des,map[i][j]);
            }
        }
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                if((i+j)%2==0)
                {
                    for(k=0;k<4;k++)
                    {
                        int x=i+dir[k][0];
                        int y=j+dir[k][1];
                        if(x>=1 && x<=n && y>=1 && y<=m)
                        {
                            add((i-1)*m+j,(x-1)*m+y,INF);
                        }
                    }
                }
            }
        }
        printf("%d
",sum-EK());
    }
    return 0;
}
趁着还有梦想、将AC进行到底~~~by 452181625
原文地址:https://www.cnblogs.com/hate13/p/4209760.html