链接: 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 #includeC - Magical Rearrangement#include #include using namespace std; const int N = 555; int n, m; typedef pair PII; int a[N][N]; vector 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; }
题意:
给出
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时,那就不行
#includeusing 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("%dn", 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
如果你有任何建议或者批评和补充,请留言指出,不胜感激
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)