• [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
  • 相关阅读:
    设计模式之单例模式实践
    有关集合的foreach循环里的add/remove
    项目中常用的MySQL优化方法--壹拾玖条
    Solr
    Lucene补充
    Lucene
    一千行 MySQL 学习笔记
    Servlet
    CSS未知宽高元素水平垂直居中
    深拷贝和浅拷贝
  • 原文地址:https://www.cnblogs.com/hate13/p/4209760.html
Copyright © 2020-2023  润新知