网易互娱9.27号19点研发岗笔试题解

一共四道编程. 前两道比较简单就不说了, 主要讲讲3,4道.

第三题: 开心消消乐
就是给你个M*N的二维矩阵, 每个块有一个颜色, 如果它的四周有相同的颜色那么就是连在一起的, 每次点击一个色块(要能点击消除尽量多的, 如果有数量相同的点击编号小的)进行消除, 然后消除后上面的掉下来, 如果某一列消失了, 右边的补过来. 问最后这个矩阵还剩多少个方块…

题解: 按照题意模拟即可, 每次dfs找出能消除最多的, 然后标记这些块, 再写个函数处理一下消除后的填充小果果, 一直处理下去就行. 考查代码力.
AC Code

const int M = 55;
const int N = 25;
bool vis[M][N];
char s[M][N], ts[M][N];
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};
int n, m;
void dfs(int x, int y, int &cnt, int flag) { // 找消除块, 还能标记这些块
    vis[x][y] = 1; ++ cnt;
    if (flag) ts[x][y] = '#';
    for (int i = 0 ; i < 4 ; ++ i) {
        int xx = x + dx[i];
        int yy = y + dy[i];
        if (xx < 1 || xx > m || yy < 1 || yy > n) continue;
        if (s[xx][yy] != s[x][y] || vis[xx][yy] || s[xx][yy] == '#') continue;
        dfs(xx, yy, cnt, flag);
    }
}
void work() {  // 处理消除这些块后矩阵的样子
    for (int i = 1 ; i <= n ; ++ i) {
        int low = m, high = m-1;
        while(low >= 1 && high >= 1) {
            if (ts[low][i] != '#') -- low;
            else {
                high = low - 1;
                while(high >= 1 && ts[high][i] == '#') -- high;
                if (high >= 1) {
                    swap(ts[low][i], ts[high][i]);
                    -- low;
                }
            }
        }
    }
    int f = 0;
    for (int i = 1 ; i < n ; ++ i) {
        if (ts[m][i] == '#') {
            f = 1;
            for (int j = 1 ; j <= m ; ++ j) {
                ts[j][i] = ts[j][i+1];
            }
            ts[m][i+1] = '#';
        }
    }
    if (f) for (int j = 1 ; j <= m ; ++ j) ts[j][n] = '#';
    memcpy(s, ts, sizeof(s));
}

void solve() {
    scanf("%d%d", &m, &n);
    for (int i = 1 ; i <= m ; ++ i) {
        scanf("%s", s[i]+1);
    }
    int tot = 0;
    int ti = 0;
    while(1) {
        ++ ti;
        memset(vis, 0, sizeof(vis));
        int mx = 0, sx = -1, sy = -1;
        for (int i = 1 ; i <= m ; ++ i) {
            for (int j = 1 ; j <= n ; ++ j) {
                if (s[i][j] == '#' || vis[i][j]) continue;
                int cnt = 0;
                dfs(i, j, cnt, 0);
                if (cnt > mx) {
                    mx = cnt; sx = i, sy = j;
                }
                else if (cnt == mx && s[i][j] - '0' < s[sx][sy] - '0') {
                    sx = i, sy = j;
                }
            }
        }
        tot += mx <= 1 ? 0 : mx;
        if (mx <= 1) break;
        int cnt = 0;
        memset(vis, 0, sizeof(vis));
        memcpy(ts, s, sizeof(s));
        dfs(sx, sy, cnt, 1);
        work();
    }
    printf("%d\n", m*n - tot);
}

第四题: 数矩形
在这里插入图片描述在这里插入图片描述在这里插入图片描述
1
4
1 1
2 2
3 3
4 4
输出5
题解: 这道题还是挺有意思的… 通过画图可以知道, 实际上就看能多分割出多少个矩形, 如果x2 < x1, 但是y2 > y1, 那就多分出了一个矩形了, 实际上有点像偏序, 也就是在确定好x的大小关系后, 寻找 当前比这个y小的有多少个, 有多少就加多少(注意处理x或者y相同的情况). 所以我们需要一个数据结构可以帮我们判断出某个数是否在里面, 比某个数小的数量是多少. 很明显set(无法算数量)做不到, 我们要做的就是模拟这个功能的set, 我用的离散化 + 树状数组.

AC Code

const int maxn = 1e5+5;

struct BinaryIndexTree {  // 离散化 + 树状数组的模板
    int a[maxn], c[maxn], idx,  siz;
    bool d[maxn];

    BinaryIndexTree() {clear();}

    void push_back(int x){a[++idx]=x;}

    int size() {return siz;}

    void build() {
        sort(a+1, a+1+idx);
        idx = unique(a+1, a+1+idx) - a - 1;
    }

    bool exist(int x){ return d[get(x)]; }

    int get(int x) {
        return lower_bound(a+1, a+1+idx,x) - a;
    }

    void insert(int x) {
        int y = get(x);
        ++siz, d[y]=true;
        for(int i = y ; i <= idx ; i += i&-i)
            ++ c[i];
    }

    int sum(int p) {
        int res = 0;
        for(int i = p ; i ; i -= i&-i)
            res += c[i];
        return res;
    }

    //<=x的数的个数
    int lower(int x){ return sum(get(x)); }

    void clear() {
        for(int i = 0 ; i <= idx ; ++i)
            c[i] = d[i] = 0;
        idx = siz =0;
    }
}bit;

struct node {
    int x,y;
    bool operator<(const node &_) const {
        if (x != _.x) return x > _.x;
        return y > _.y;
    }
}a[maxn];

void solve() {
    int n;
    scanf("%d",&n);
    for (int i = 1 ; i <= n ; ++ i) {
        scanf("%d%d",&a[i].x,&a[i].y);
        bit.push_back(a[i].y);
    }
    sort(a+1,a+1+n);
    bit.build();
    ll ans=0;
    for(int i = 1 ; i <= n ; ++i) {
        if(a[i].x != a[i-1].x) // x相同, 不用计算小的值
            ans+=bit.lower(a[i].y);
        if(!bit.exist(a[i].y)) {
            ++ans; // 本身, 然后再把不在set的y插进去. 不重复加
            bit.insert(a[i].y);
        }
    }
    printf("%lld\n",ans);
    bit.clear();
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页