Comet OJ - Contest #13

第一次打comet oj,菜

A 水題

C1

題意:類比油井問題,然後q次操作,把以(x1, y1)爲左上角和以(x2,y2)爲右下角的地圖置爲1,再找有多少個連通塊。

簡單版本的可以每次直接搜索,類似於油井問題

#include <bits/stdc++.h>
using namespace std;
#define ll   long long
const int N = 2e5+10;
int dx[4][2] = {1,0,-1,0,0,1,0,-1};
int a[N], n, m;
char s[400][400];
bool vis[400][400];
bool ok(int x, int y)
{
    if(x<0||x>=n||y<0||y>=m||vis[x][y]||s[x][y]!='1') return false;
    return true;
}
void dfs(int x, int y)
{
    vis[x][y] = 1;
    for(int i = 0; i < 4; ++i)
    {
        int nx = x+dx[i][1], ny = y+dx[i][0];
        if(ok(nx, ny))
            dfs(nx, ny);
    }
}
int test()
{
    memset(vis, 0, sizeof(vis));
    int ans = 0;
    for(int i = 0; i < n; ++i)
        for(int j = 0; j < m; ++j)
        if(s[i][j] == '1'&&!vis[i][j]) {
            ans++;  dfs(i, j);
        }
    return ans;
}
void solve()
{
    int x1, y1, x2, y2;
    scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
    x1--; y1--; x2--; y2--;
    for(int x = x1; x <= x2; ++x)
        for(int y = y1; y <= y2; ++y)
        s[x][y] = '1';
    int ans = test();
    printf("%d\n", ans);
}
int main ()
{
    while(~scanf("%d%d", &n, &m)) {
        for(int i = 0; i < n; ++i) scanf("%s", s[i]);
        int t; scanf("%d", &t);
        while(t--)  solve();
    }
    return 0;
}

B

題意:一個地圖,一個字符串記錄移動方向,遇到蘋果,蛇身長加一,輸出移動後的地圖,撞牆就GG

我看很多大佬用的是隊列,其實我剛開始也想用的,後來發現數據範圍不是很大,用數組模擬的話也不會超內存,其實隊列更方便。於是我用slen當蛇頭,sw當蛇尾,當遇到蘋果時蛇頭進一,沒遇到就sw+1,蛇頭進一。注意吧喫過的蘋果置爲空就行,最後直接從sw到slen把蛇放上去,中間如果死亡,直接跳出。

#include <bits/stdc++.h>
using namespace std;
const int N = 4e5+10;
int dx[4][2] = {-1,0,0,-1,1,0, 0,1}; // wasd上下左右
int  n, m, len, nx, ny, slen, sw;
map<char, int> mp;
char s[410][410], dir[N];
struct node
{
    int x, y;
}a[N];
void init();
bool ok1(int x, int y);
bool ok(int x, int y)
{
    if(x<0||x>=n||y<0||y>=m)
        return false;
    return true;
}
int main ()
{
    init();
    scanf("%d%d", &n, &m);
    for(int i = 0; i < n; ++i)
    {
        scanf("%s", s[i]);
        for(int j = 0; j < m; ++j)
            if(s[i][j] == '@') {
                a[slen].x = i, a[slen++].y = j;
                s[i][j] = '.';
            }

    }
    scanf("%s", dir);
    len = strlen(dir);
    int flag = true; sw = 0;
    for(int i = 0; i < len; ++i)
    {
        int x = a[slen-1].x, y = a[slen-1].y;
        x += dx[mp[dir[i]]][0], y += dx[mp[dir[i]]][1];
            if(!ok(x, y)) {
                flag = false;
                break;
            }
            if(s[x][y] == 'o') {
                s[x][y] = '.';
                a[slen].x = x;
                a[slen++].y = y;
            }
            else
            {
                sw++;
                a[slen].x = x;
                a[slen++].y = y;
            }
    }
    if(!flag) printf("GG\n");
    else {
       for(int i = sw; i < slen; ++i) {
        s[a[i].x][a[i].y] = 'X';
        if(i == slen-1)
        s[a[i].x][a[i].y] = '@';
       }
       for(int i = 0; i < n; ++i) printf("%s\n", s[i]);
    }
    return 0;
}
void init()
{
    slen = 0;
    mp['W'] = 0; mp['A'] = 1;mp['S'] = 2; mp['D'] = 3;
}
bool ok1(int x, int y)
{
    if(x<0||x>=n||y<0||y>=m||s[x][y]!='X')
        return false;
    return true;
}

C2

C1的困難版本,數據範圍大,顯然搜索已經不行了。不太會,我也是照着題解看的…
每個格子只會從0變成1,在從0變成1時訪問,並查級把每個位置對應的祖先設爲右邊最先爲0的列
另一個用來記錄個數

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
int dx[4][2] = {1,0,-1,0,0,1,0,-1};
int n, m, ans, u, v;
char Map[1010][1010];
int id[1010][1010],Fa[1010][1010], book[N];

int Find(int *f, int x)
{
    return f[x] == x?x:f[x] = Find(f, f[x]);
}
void solve(int x,int y)
{
    static int tot = 0;
    ans++; id[x][y] = ++tot; book[tot] = tot;
    u = Find(Fa[x], y), v = Find(Fa[x], y+1);
    if(u!=v) Fa[x][u] = v;
    for(int i = 0; i < 4; ++i)
    {
        int nx = x+dx[i][0], ny = y+dx[i][1];
        if(nx&&ny&&nx<=n&&ny<=m&&id[nx][ny])
        {
            u = Find(book, tot), v = Find(book, id[nx][ny]);
            if(u!=v)
                ans--, book[u] = v;
        }
    }
}
int main ()
{
    freopen("in.txt", "r", stdin);
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) scanf("%s", Map[i]+1);

    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m+1; ++j)
            Fa[i][j] = j;
    
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
            if(Map[i][j]=='1')
               solve(i, j);
    int t;
    scanf("%d", &t);
    while(t--) {
        int x1,x2,y1,y2;
        scanf("%d%d%d%d", &x1, &y1,&x2,&y2);
        for(int x = x1; x <= x2; ++x)
            for(int y = Find(Fa[x], y1); y <= y2; y = Find(Fa[x], y))
                solve(x, y);
        printf("%d\n", ans);
    }
    return 0;
}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章