2021 Jiangsu Collegiate Programming Contest(CJ)

Posted 佐鼬Jun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021 Jiangsu Collegiate Programming Contest(CJ)相关的知识,希望对你有一定的参考价值。

链接: link.

J - Anti-merge

题意:
给定一个 N × M N×M N×M的矩阵,矩阵内相同的数字相邻时有按照列优先行其次的优先级进行合并,现在让你给一些数字贴上标签,若两个相邻数字相同但标签不同时,不会合并,但标签一样,数字一样时,会合并,问最少贴多少种标签,且在标签种类最少时,最少贴多少个标签
思路:
如果矩阵中不会出现合并现象,即没有相邻数字一样时,直接就输出 0 0 0即可。
如果矩阵中有合并现象,那么 标签种类一定最少一定是 1 1 1,因为合并现象指挥发生在相邻且相同的数字之间,那么只需要给相同数字且相邻的贴上标签 1 1 1,另一个不贴标签,就能区分开两种数字,使其不合并,所以标签种类最少是 1 1 1,标签种类为 1 1 1的情况下,就是二分图染色,把格点看成图中的点,相邻就是连边,那么直接跑二分图就行,对每一个部分染色后,看哪种颜色少,就把哪种存到答案中。

#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
const int N = 555;
int n, m;
typedef pair<int, int> PII;
int a[N][N];
vector<PII> ans[4];
int color[N][N];
int dx[4] = -1, 1, 0, 0;
int dy[4] = 0, 0, -1, 1;

int check(int x, int y) 
    int flag1 = 0, flag2 = 0;
    if (x - 1 > 0 && a[x - 1][y] == a[x][y]) flag1 = 1;
    if (y - 1 > 0 && a[x][y - 1] == a[x][y]) flag2 = 1;
    return (flag1 | flag2);


bool dfs(int x, int y, int c) 
    color[x][y] = c;
    ans[c].push_back(x, y);
    for (int i = 0; i < 4; i++) 
        int nx = x + dx[i];
        int ny = y + dy[i];
        if (nx < 1 || nx > n || ny < 1 || ny > m || a[x][y] != a[nx][ny]) 
            continue;
        
        if (!color[nx][ny]) 
            if (!dfs(nx, ny, 3 - c)) return 0;
         else if (color[nx][ny] == c) 
            return 0;
        
    
    return 1;

int main() 
    cin >> n >> m;
    for (int i = 1; i <= n; i++) 
        for (int j = 1; j <= m; j++) 
            scanf("%d", &a[i][j]);
        
    

    int types = 0;
    for (int i = 1; i <= n; i++) 
        for (int j = 1; j <= m; j++) 
            if (check(i, j)) 
                types = 1;
                break;
            
        
        if (types) break;
    
    if (!types) 
        puts("0 0");
     else 
        for (int i = 1; i <= n; i++) 
            for (int j = 1; j <= m; j++) 
                ans[1].clear();
                ans[2].clear();
                if (!color[i][j]) 
                    dfs(i, j, 1);
                
                if (ans[1].size() > ans[2].size()) 
                    for (int k = 0; k < ans[2].size(); k++) 
                        ans[0].push_back(ans[2][k]);
                    
                 else 
                    for (int k = 0; k < ans[1].size(); k++) 
                        ans[0].push_back(ans[1][k]);
                    
                
            
        
        cout << types << " " << ans[0].size() << endl;
        for (int i = 0; i < ans[0].size(); i++) 
            cout << ans[0][i].first << " " << ans[0][i].second << " "
                 << "1" << endl;
        
    
    return 0;


C - Magical Rearrangement

题意:
给出 0 − 9 0-9 09每个数字的个数,现在要构造出一个没有前导 0 0 0( 0 0 0本身除外),且相邻数字不能一样的数字,这个数字最小是多少?
思路:
从小到大贪心,在贪心过程中,每次取一个数的时候判断即可,如果剩下的数字总数为 s u m sum sum,最大的数量为 m a x v maxv maxv
如果这个最大的数量就是拿的这个数,那么 2 ∗ m a x v − s u m ≥ 1 2*maxv-sum≥1 2maxvsum1时,那就不行
如果这个最大数量不是拿的这个数,那么 2 ∗ m a x v − s u m > 1 2*maxv-sum>1 2maxvsum>1时,那就不行

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[11];
int res[N];

bool check(int u) 
    int sum = 0;
    int maxv = 0;
    for (int i = 0; i < 10; i++) 
        sum += a[i];
        maxv = max(maxv, a[i]);
    
    for (int i = 0; i < 10; i++) 
        if (a[i] == maxv) 
            if (i == u) 
                if (2 * maxv - sum >= 1) 
                    return 0;
                
             else 
                if (2 * maxv - sum > 1) 
                    return 0;
                
            
        
    
    return 1;

int main() 
    int T;
    cin >> T;
    while (T--) 
        int all = 0;
        for (int i = 0; i < 10; i++) 
            scanf("%d", &a[i]);
            all += a[i];
        
        memset(res, 0, (all + 2) * 4);
        if (all == 1) 
            for (int i = 0; i < 10; i++) 
                if (a[i]) 
                    printf("%d\\n", i);
                
            
         else 
            bool flag = 1;
            int ed = all;
            int st = 0;
            while (st < ed) 
                bool f = 1;
                for (int i = 0; i < 10; i++) 
                    if (st == 0 && i == 0) continue;
                    if (a[i] == 0) continue;
                    if (st != 0 && res[st - 1] == i) continue;
                    a[i]--;
                    if (check(i)) 
                        res[st++] = i;
                        f = 0;
                        break;
                     else 
                        a[i]++;
                    
                
                if (f) 
                    flag = 0;
                    break;
                
            
            if (flag == 0) 
                puts("-1");
             else 
                for (int i = 0; i < st; i++) 
                    cout << res[i];
                
                puts("");
            
        
    
    return 0;

剩下的待补
To be continued
如果你有任何建议或者批评和补充,请留言指出,不胜感激

以上是关于2021 Jiangsu Collegiate Programming Contest(CJ)的主要内容,如果未能解决你的问题,请参考以下文章

2021 Jiangsu Collegiate Programming Contest(CJ)

2021江苏税务社保缴纳微信小程序http://gyxzaz2.hguifeio.com/522/rj_css1/jiangsu

2023 Hubei Provincial Collegiate Programming Contest(gym104337)I. Step

2020 China Collegiate Qinhuangdao Site E. Exam Results(尺取)

The 2021 Shanghai Collegiate D. Zztrans 的班级合照(清新小dp)

ZJCPC2021 第18届 浙江省赛The 18th Zhejiang Provincial Collegiate Programming Contest(ACFGJLM 7题)