[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\n",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\n",sum-EK());

    }

    return 0;

}

 

你可能感兴趣的:(HDU)