zoukankan      html  css  js  c++  java
  • [USACO18OPEN]Multiplayer Moo

    题目描述

    奶牛们提出了一款创新性的新游戏,惊讶的是她们给这款游戏取了个最没创意的名字:“Moo”。 Moo游戏在一个由 N×N 个正方形格子组成的棋盘上进行,一头奶牛可以通过大叫一声“哞!”然后把她的数字编号写在这个格子里来占有这个格子。

    在游戏结束的时候,每个格子中都包含一个数。在这个时刻,如果一头奶牛创建了一个由连通的格子组成的领域,大小不小于其他所有领域,那这头奶牛就获胜。一个“领域”被定义为一些具有相同数字编号的格子,其中每个在领域中的格子都直接与另一个同一领域中的格子通过上、下、左或者是右相邻(对角线不计)。

    由于以单牛形式进行游戏有点无聊,奶牛们也对双牛组队进行游戏感兴趣。同一队的两头奶牛像之前一样可以创建一个领域,但是现在领域中的格子可以属于队伍中的任一头奶牛。

    给定游戏棋盘的最终状态,请帮助奶牛们计算任何单头奶牛拥有的最大的领域包含的格子数量,以及任何两头奶牛组成的队伍占有的最大的领域包含的格子的数量。两头奶牛占有的领域必须要同时包含队伍中两头奶牛的编号,不能仅仅包含一头。

    输入输出格式

    输入格式:

    输入的第一行包含 N ( 1N250 )。下面 NN 行,每行包含 NN 个整数(每个都在 0--1e6 之间),描述棋盘的最终状态。棋盘中至少出现两种不同的数字。

    输出格式:

    输出的第一行描述任何单头奶牛占有的最大领域大小,第二行描述任何两头奶牛的队伍占有的最大领域的大小。

    输入输出样例

    输入样例#1:
    4
    2 3 9 3
    4 9 9 1
    9 9 1 7
    2 1 1 9
    输出样例#1:
    5
    10
    

    说明

    在这个例子中,单头奶牛占有的最大领域是由五个9组成的。如果编号为1和9的奶牛组队,她们可以形成一个大小为10的领域。

    题解: 第一个数很好算,DFS一边就行,并给每一个联通块序列化,然后在for扫一遍将建立关系,因为可能会出现重复,所以用set去重一下,然后枚举一个点到另一点,DFS ,删除经过的边。因为每一次DFS需要标记点,不能每一次都初始化,可以用一个栈存储,每一次搜索完后,对栈的中标记的数操作。

    c++ code:

    #include <bits/stdc++.h>
    #define IT set<Node>::iterator
    using namespace std;
    
    const int N =300 + 10;
    int mmap[N][N],flag[N][N],num[N*N],dig[N*N];
    bool vis[N][N],vised[N*N];
    int cnt;
    int dir[4][2]={1,0,0,1,0,-1,-1,0},tot,n,cot,head[N*N*4];
    stack<int>sta;
    struct Edge{
        int to,next,flag;
    }edge[N*N*4];
    void add(int u,int v)
    {
        edge[cot].next=head[u];
        edge[cot].to=v;
        edge[cot].flag = 1;
        head[u]=cot++;
    }
    
    struct Node{
        int u,v;
        bool operator<(const Node &b) const
        {
            return u == b.u?v < b.v:u < b.u;
        }
    };
    
    set<Node>s;
    int dfs(int x,int y)
    {
        int ans = 0;
        vis[x][y] = true;
        flag[x][y] = tot;
        for(int i = 0;i < 4;i++)
        {
            int dx = x + dir[i][0],dy = y + dir[i][1];
            if(dx >= 1 && dx <= n && dy >= 1 && dy <= n && !vis[dx][dy] && mmap[x][y] == mmap[dx][dy])
                ans += dfs(dx,dy) + 1;
        }
        return ans;
    }
    
    void LK()
    {
        for(int i = 1;i <= n;i++)
            for(int j = 1;j <= n;j++)
            {
                for(int k = 0;k < 4;k++)
                {
                    int dx = i + dir[k][0],dy = j + dir[k][1];
                    Node now;
                    if(dx >= 1 && dx <= n && dy >= 1 && dy <= n && flag[i][j] != flag[dx][dy])
                    {
                        now.u = flag[dx][dy];now.v = flag[i][j];
                        if(now.u > now.v)
                            swap(now.u,now.v);
                        s.insert(now);
                    }
                }
            }
    }
    
    int dfs(int now,int val1,int val2)
    {
        int ans = num[now];
        vised[now] = true;
        sta.push(now);
        for(int i=head[now];i != -1;i = edge[i].next)
        {
            int to = edge[i].to;
            if(!vised[to] && (dig[to] == val1 || dig[to] == val2) && edge[i].flag)
            {
                edge[i].flag = 0;
                ans += dfs(to,val1,val2);
            }
        }
        return ans;
    }
    
    int solve(int now)
    {
        int ans = 0;
        for(int i=head[now];i != -1;i = edge[i].next)
        {
            int to = edge[i].to;
            if(!vised[to] && edge[i].flag)
            {
                int val = dfs(now,dig[to],dig[now]);
                ans = max(val,ans);
                while(!sta.empty())
                    vised[sta.top()] = false,sta.pop();
            }
        }
        vised[now] = true;
        return ans;
    }
    
    int main()
    {
        tot = 0;cot = 0;
        memset(vis,false,sizeof(vis));
        memset(flag,0,sizeof(flag));
        for(int i = 0; i < N*N*4;i++)
            head[i] = -1;
        scanf("%d",&n);
        for(int i = 1;i <= n;i++)
            for(int j = 1;j <= n;j++)
                scanf("%d",&mmap[i][j]);
        int ans = 0,ant = 0;
        for(int i = 1;i <= n;i++)
            for(int j = 1;j <= n;j++)
                if(!vis[i][j])
                {
                    ++tot;
                    int val = dfs(i,j)+1;
                    ans = max(ans,val);
                    num[tot] = val;
                    dig[tot] = mmap[i][j];
                }
        LK();
        Node node;
        for(IT it = s.begin();it != s.end();it++)
        {
            node = *it;
            add(node.u,node.v);
            add(node.v,node.u);
        }
        memset(vised,false,sizeof(vised));
        for(int i = 1;i <= tot;i++)
            ant = max(ant,solve(i));
        printf("%d
    %d
    ",ans,ant);
        return 0;
    }
  • 相关阅读:
    随笔
    json对象的默认排序问题
    SQl死锁随想
    疑惑
    .netportal
    WCF中出现方法出现无法匹配的异常
    自动播放图片,可以调整速度。
    一个二级树形菜单,初始显示为全部展开,适用于分类较少的情况。
    整理了一下以后需要用的软件
    缩略图,大图,同页显示
  • 原文地址:https://www.cnblogs.com/lemon-jade/p/9375480.html
Copyright © 2011-2022 走看看