[关闭]
@Dmaxiya 2018-08-17T10:24:56.000000Z 字数 6466 阅读 1170

Codeforces Round #492 (Div. 1)

Codeforces


Contests 链接:Codeforces Round #492 (Div. 1)
过题数:1
排名:409/663

A. Tesla

题意

在一个 停车场上,第 行和第 行是停车位,第 行和第 行是车行道,如下图:

总共有 辆车,分别编号为 ,每辆车都要停到与车辆编号相同的停车位上。每辆车每次只能移动到相邻的坐标上,且编号为 的车辆只允许在车行道上行驶或者进入编号为 的停车位内,不允许进入其他编号的停车位与没有编号的停车位上。问是否能找到一种移动次数在 次内的车辆行驶方案,使得所有车都进入到对应的停车位,如果可以,则输出车辆行驶路线,否则输出

输入

第一行包括两个整数 ,接下去四行每行 个整数,第 行和第 行的非零数字表示对应编号的停车位, 表示禁止进入的停车位,第 行和第 行非零数字表示对应编号的车的位置, 表示空地,其他车辆可以移动到该处。

输出

如果无法在 步内将所有车辆移动到对应的停车位,则输出 ,否则第一行输出一个整数 表示需要的移动次数,接下去 行每行三个整数 ,表示第 辆车移动到第 行第 列的位置上,移动的位置必须保证合法。如果有多解则输出任意一组。

样例

输入 输出 提示
4 5
1 2 0 4
1 2 0 4
5 0 0 3
0 5 0 3
6
1 1 1
2 1 2
4 1 4
3 4 4
5 3 2
5 4 2
除了车辆 ,其他车辆都在相应的停车位旁,样例输出给出的是到达相应停车位的最快的方式,
其他任何一种移动次数小于 次的方案都是允许的。
1 2
1
2
1
2
-1 所有车辆都在一列内,且他们的相对位置导致它们无法回到自己的停车位内,所以只能输出
1 2
1
1
2
2
2
1 1 1
2 4 1

题解

可以将所有车辆按顺时针或者逆时针的顺序在第 行内移动,每次移动,检查车辆位置是否在对应停车位旁,如果是,则直接进入停车位,否则继续跟着所有车辆移动。可以计算得出,最坏情况下 所有车辆需要的移动次数为 ,如果无法顺/逆时针移动,车辆也无法进入停车位,则输出

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <sstream>
  6. #include <cstring>
  7. #include <string>
  8. #include <vector>
  9. #include <list>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #include <set>
  14. #include <algorithm>
  15. using namespace std;
  16. #define LL long long
  17. const int maxn = 500;
  18. const int maxcnt = 20000 + 100;
  19. struct Node {
  20. int x, y;
  21. Node() {}
  22. Node(int xx, int yy) {
  23. x = xx;
  24. y = yy;
  25. }
  26. };
  27. bool operator!=(const Node &a, const Node &b) {
  28. return a.x != b.x || a.y != b.y;
  29. }
  30. int n, k, anscnt, cnt;
  31. int num[4][maxn];
  32. Node pre[4][maxn];
  33. bool vis[4][maxn];
  34. int ans[maxcnt][3];
  35. const int dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
  36. bool in(int x, int y) {
  37. return x >= 1 && x <= 2 && y >= 0 && y < n;
  38. }
  39. void dfs(int x, int y) {
  40. for(int i = 0; i < 4; ++i) {
  41. int xx = x + dir[i][0];
  42. int yy = y + dir[i][1];
  43. if(in(xx, yy) && !vis[xx][yy]) {
  44. vis[xx][yy] = true;
  45. pre[xx][yy] = Node(x, y);
  46. dfs(xx, yy);
  47. }
  48. }
  49. }
  50. void get_in() {
  51. for(int i = 1; i <= 2; ++i) {
  52. for(int j = 0; j < n; ++j) {
  53. if(num[i][j] != 0 && num[i][j] == num[i ^ 1][j]) {
  54. ans[anscnt][0] = num[i][j];
  55. ans[anscnt][1] = (i ^ 1) + 1;
  56. ans[anscnt][2] = j + 1;
  57. anscnt++;
  58. num[i][j] = 0;
  59. --cnt;
  60. }
  61. }
  62. }
  63. }
  64. bool Go() {
  65. for(int i = 1; i <= 2; ++i) {
  66. for(int j = 0; j < n; ++j) {
  67. if(num[i][j] == 0) {
  68. Node Begin = Node(i, j);
  69. Node first = pre[Begin.x][Begin.y];
  70. Node second = Begin;
  71. while(first != Begin) {
  72. if(num[first.x][first.y] != 0) {
  73. ans[anscnt][0] = num[first.x][first.y];
  74. ans[anscnt][1] = second.x + 1;
  75. ans[anscnt][2] = second.y + 1;
  76. ++anscnt;
  77. }
  78. swap(num[first.x][first.y], num[second.x][second.y]);
  79. second = first;
  80. first = pre[second.x][second.y];
  81. }
  82. return true;
  83. }
  84. }
  85. }
  86. return false;
  87. }
  88. int main() {
  89. #ifdef Dmaxiya
  90. freopen("test.txt", "r", stdin);
  91. #endif // Dmaxiya
  92. ios::sync_with_stdio(false);
  93. while(scanf("%d%d", &n, &k) != EOF) {
  94. anscnt = 0;
  95. cnt = k;
  96. memset(vis, 0, sizeof(vis));
  97. for(int i = 0; i < 4; ++i) {
  98. for(int j = 0; j < n; ++j) {
  99. scanf("%d", &num[i][j]);
  100. }
  101. }
  102. dfs(1, 0);
  103. bool flag;
  104. do {
  105. get_in();
  106. flag = Go();
  107. } while(flag && cnt != 0);
  108. if(cnt != 0) {
  109. printf("-1\n");
  110. continue;
  111. }
  112. printf("%d\n", anscnt);
  113. for(int i = 0; i < anscnt; ++i) {
  114. for(int j = 0; j < 3; ++j) {
  115. if(j != 0) {
  116. printf(" ");
  117. }
  118. printf("%d", ans[i][j]);
  119. }
  120. printf("\n");
  121. }
  122. }
  123. return 0;
  124. }

B. Suit and Tie

题意

对夫妻,他们坐在一排,每对夫妻之间的位置不一定是相邻的,如果每次只能将相邻位置的两个人交换位置,问最少要交换多少次才能让所有夫妻坐在相邻的位置上。

输入

第一行为一个整数 ,第二行为 个整数 ,数据保证 的每个数字只出现 次。

输出

输出最少的交换次数。

样例

输入 输出 提示
4
1 1 2 3 3 2 4 4
2 可以通过下面的交换达到结果:

也可以通过下面的交换达到结果:
3
1 1 2 2 3 3
0 已经使得所有夫妻座位相邻,因此不需要进行任何交换。
3
3 1 2 3 1 2
3

题解

对于每个数字中在左边的那个,去找另一个数字,将另一个数字移动到左边的数字旁边, 依次贪心下去,就能得到最短的移动步数。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <sstream>
  6. #include <cstring>
  7. #include <string>
  8. #include <vector>
  9. #include <list>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #include <set>
  14. #include <algorithm>
  15. using namespace std;
  16. #define LL long long
  17. const int maxn = 300;
  18. int n;
  19. int num[maxn];
  20. int Find(int Index, int x) {
  21. for(int i = Index; i <= n; ++i) {
  22. if(num[i] == x) {
  23. return i;
  24. }
  25. }
  26. return -1;
  27. }
  28. int main() {
  29. #ifdef Dmaxiya
  30. freopen("test.txt", "r", stdin);
  31. #endif // Dmaxiya
  32. ios::sync_with_stdio(false);
  33. while(scanf("%d", &n) != EOF) {
  34. int ans = 0;
  35. n *= 2;
  36. for(int i = 1; i <= n; ++i) {
  37. scanf("%d", &num[i]);
  38. }
  39. for(int i = 1; i <= n; ++i) {
  40. int End = Find(i + 1, num[i]);
  41. if(End != -1) {
  42. for(int j = End - 1; j > i; --j) {
  43. swap(num[j], num[j + 1]);
  44. ++ans;
  45. }
  46. }
  47. }
  48. printf("%d\n", ans);
  49. }
  50. return 0;
  51. }

C. Leaving the Bar

题意

给定 个向量,要求对每个向量分配一个系数 ,使得所有向量乘上对应的系数后相加得到的最终的向量模长不超过

输入

第一行包含一个整数 ,接下去 行每行两个整数 ,表示第 个向量的值 ,数据保证每一个向量的模长

输出

输出一行,包含 个整数 ,每个整数必须为 ,表示每个向量对应的系数,输出必须保证 。如果有多解输出任意一组即可。

样例

输入 输出
3
999999 0
0 999999
999999 0
1 1 -1
1
-824590 246031
1
8
-67761 603277
640586 -396671
46147 -122580
569609 -2112
400 914208
131792 309779
-850150 -486293
5272 721899
1 1 1 1 1 1 1 -1

题解

由如下断言:

对于任意三个模长小于 的向量 个向量中,两两之间夹角最小的角度最大为 ,将这两个夹角小于 的向量做差,则得到的新向量的长度一定不大于

可知,可以将 个向量每 个之间选择两个求和或做差,最终得到的向量模长一定不大于 ,合并到只剩下两个向量时,这两个向量所在的直线夹角最大为 ,将这两个向量求和或做差,得到的向量长度最大为

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <sstream>
  6. #include <cstring>
  7. #include <string>
  8. #include <vector>
  9. #include <list>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #include <set>
  14. #include <algorithm>
  15. using namespace std;
  16. #define LL long long
  17. const int maxn = 200000 + 100;
  18. struct Node {
  19. LL x, y;
  20. int l, r;
  21. Node() {}
  22. Node(LL xx, LL yy) {
  23. x = xx;
  24. y = yy;
  25. }
  26. double length() {
  27. return sqrt(x * x + y * y);
  28. }
  29. LL mult(const Node &n) {
  30. return x * n.x + y * n.y;
  31. }
  32. Node operator-() {
  33. return Node(-x, -y);
  34. }
  35. };
  36. LL operator*(const Node &a, const Node &b) {
  37. return a.x * b.y - a.y * b.x;
  38. }
  39. Node operator-(const Node &a, const Node &b) {
  40. return Node(a.x - b.x, a.y - b.y);
  41. }
  42. int n, cnt;
  43. int ans[maxn], the_Index[3];
  44. Node node[maxn];
  45. bool Close(Node &a, Node &b) {
  46. if(a.mult(b) < 0) {
  47. return false;
  48. }
  49. LL tmp = abs(a * b);
  50. return tmp <= a.length() * b.length() / 2 * sqrt(3.0);
  51. }
  52. int Creat_Node(const Node &n, int l, int r) {
  53. ++cnt;
  54. node[cnt] = n;
  55. node[cnt].l = l;
  56. node[cnt].r = r;
  57. return cnt;
  58. }
  59. void Solve() {
  60. sort(the_Index, the_Index + 3);
  61. do {
  62. int l = the_Index[0];
  63. int r = the_Index[1];
  64. Node tmp = node[l];
  65. Node ntmp = node[r];
  66. if(Close(tmp, ntmp)) {
  67. ans[l] = 1;
  68. ans[r] = -1;
  69. int Index = Creat_Node(tmp - ntmp, l, r);
  70. ans[Index] = 1;
  71. the_Index[0] = Index;
  72. the_Index[1] = the_Index[2];
  73. return ;
  74. }
  75. ntmp = -node[r];
  76. if(Close(tmp, ntmp)) {
  77. ans[l] = ans[r] = 1;
  78. int Index = Creat_Node(tmp - ntmp, l, r);
  79. ans[Index] = 1;
  80. the_Index[0] = Index;
  81. the_Index[1] = the_Index[2];
  82. return ;
  83. }
  84. } while(next_permutation(the_Index, the_Index + 3));
  85. }
  86. int main() {
  87. #ifdef Dmaxiya
  88. freopen("test.txt", "r", stdin);
  89. #endif // Dmaxiya
  90. ios::sync_with_stdio(false);
  91. while(scanf("%d", &n) != EOF) {
  92. cnt = 0;
  93. for(int i = 1; i <= n; ++i) {
  94. scanf("%I64d%I64d", &node[i].x, &node[i].y);
  95. node[i].l = node[i].r = 0;
  96. ++cnt;
  97. }
  98. if(n == 1) {
  99. printf("1\n");
  100. continue;
  101. }
  102. ans[1] = 1;
  103. the_Index[0] = 1;
  104. the_Index[1] = 2;
  105. for(int i = 3; i <= n; ++i) {
  106. the_Index[2] = i;
  107. Solve();
  108. }
  109. int l = the_Index[0];
  110. int r = the_Index[1];
  111. if(node[l].mult(node[r]) >= 0) {
  112. ans[r] = -1;
  113. } else {
  114. ans[r] = 1;
  115. }
  116. for(int i = cnt; i >= 1; --i) {
  117. ans[node[i].l] *= ans[i];
  118. ans[node[i].r] *= ans[i];
  119. }
  120. for(int i = 1; i <= n; ++i) {
  121. if(i != 1) {
  122. printf(" ");
  123. }
  124. printf("%d", ans[i]);
  125. }
  126. printf("\n");
  127. }
  128. return 0;
  129. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注