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
0−9每个数字的个数,现在要构造出一个没有前导
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
2∗maxv−sum≥1时,那就不行
如果这个最大数量不是拿的这个数,那么
2
∗
m
a
x
v
−
s
u
m
>
1
2*maxv-sum>1
2∗maxv−sum>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)的主要内容,如果未能解决你的问题,请参考以下文章