Multiplayer Moo

Multiplayer Moo

时间限制: 2 Sec  内存限制: 256 MB
提交: 97  解决: 15
[提交] [状态] [讨论版] [命题人:admin]

题目描述

The cows have come up with a creative new game, surprisingly giving it the least creative name possible: "Moo".
The game of Moo is played on an N×N grid of square cells, where a cow claims a grid cell by yelling "moo!" and writing her numeric ID number in the cell.

At the end of the game, every cell contains a number. At this point, a cow wins the game if she has created a region of connected cells as least as large as any other region. A "region" is defined as a group of cells all with the same ID number, where every cell in the region is directly adjacent to some other cell in the same region either above, below, left, or to the right (diagonals don't count).

Since it is a bit boring to play as individuals, the cows are also interested in pairing up to play as teams. A team of two cows can create a region as before, but now the cells in the region can belong to either of the two cows on the team.

Given the final state of the game board, please help the cows compute the number of cells belonging to the largest region that any one cow owns, and the number of cells belonging to the largest region that can be claimed by a two-cow team. A region claimed by a two-cow team only counts if it contains the ID numbers of both cows on the team, not just one of the cows.

输入

The first line of input contains N (1≤N≤250). The next N lines each contain N integers (each in the range 0…106), describing the final state of the game board. At least two distinct ID numbers will be present in the board.

输出

The first line of output should describe the largest region size claimed by any single cow, and the second line of output should describe the largest region size claimed by any team of two cows.

样例输入

扫描二维码关注公众号,回复: 2450012 查看本文章
4
2 3 9 3
4 9 9 1
9 9 1 7
2 1 1 9

样例输出

5
10

提示

In this example, the largest region for a single cow consists of five 9s. If cows with IDs 1 and 9 team up, they can form a region of size 10.

来源/分类

USACO 2018 US Open Contest, Silver 

题目大意:给出一个矩阵,矩阵里边的编号代表一个牛的id,第一行让输出一个最大的联通块,第二行让两个牛组成一个团队,然后再输出最大的块是多少个。

本来我将每个块的大小排序,每次抽出来两个块合并之后搜。但是这样应该属于无脑爆搜。

结束之后听了同学和学长讲题后才明白。正确的剪枝。

正解:将每个数字(id范围0-1e6)的出现次数统计一下,然后从大到小排序。每次我们尽量合并块数较多的id,一个很好的剪枝就是如果当前两个数字的个数小于当前的暂时最优解就直接break;(因为当前块之后的块数肯定更小)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define N 100005
#define inf 0x3f3f3f3f
#define pb(x) push_back(x)
#define LL long long
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define maxn 1000005
struct node
{
    int num,k;
    node(){num=0,k=0;}
    friend bool operator < (node xx,node yy)
    {
        return xx.k>yy.k;
    }
}s[maxn];

int ans=0;
int vis[350][350];
int a[350][350];
int dx[4]={1,0,-1,0};
int dy[4]={0,-1,0,1};
int n;
void dfs(int x,int y,int step,int last1,int last2)
{
    //cout<<x<<" "<<y<<" "<<step<<" "<<last1<<" "<<last2<<endl;
    vis[x][y]=1;
    ans=max(ans,step)+1;
    rep(j,0,3)
    {
        int xx=x+dx[j];
        int yy=y+dy[j];
        if(xx<=0||x>n)continue;
        if(yy<=0||yy>n)continue;
        if(vis[xx][yy])continue;
        if(a[xx][yy]!=last1&&a[xx][yy]!=last2)continue;
        dfs(xx,yy,step+1,last1,last2);
    }
}

void init()
{
    for(int i=0;i<=maxn;i++)
    {
        s[i].k=0;
    }
}

int solve(int x,int y)
{
    int ask=0;
    rep(i,1,n)
    {
        rep(j,1,n)
        {
            if(vis[i][j])continue;
            if(a[i][j]==x||a[i][j]==y)
            {
                dfs(i,j,0,x,y);
                ask=max(ask,ans);
               // cout<<x<<" "<<y<<" "<<ask<<endl;
                ans=0;
            }
        }
    }
    return ask;
}
int main()
{
    while(cin>>n){
    init();
    memset(vis,0,sizeof(vis));
    rep(i,1,n)
    {
        rep(j,1,n)
        {
            scanf("%d",&a[i][j]);
        }
    }
    int m=0;
    rep(i,1,n)
    {
        rep(j,1,n)
        {
            if(vis[i][j])continue;
            dfs(i,j,0,a[i][j],a[i][j]);
            int tmp=a[i][j];
            s[tmp].k+=ans;
            s[tmp].num=tmp;
            m=max(m,ans);
            ans=0;
        }
    }
    cout<<m<<endl;
    sort(s,s+maxn);
    int ans2=m;
    rep(i,0,maxn)
    {
        rep(j,i+1,maxn)
        {
            if(s[i].k+s[j].k<=ans2)break;
            memset(vis,0,sizeof(vis));
            int last=solve(s[i].num,s[j].num);
            //cout<<"**************"<<endl;
            ans2=max(ans2,last);
            ans=0;
        }
    }
         cout<<ans2<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_40894017/article/details/81195613