@Dmaxiya
2018-08-17T02:27:00.000000Z
字数 6110
阅读 1118
Codeforces
Contests 链接:Codeforces Round #488 (Div. 1)
过题数:2
排名:295/715
按顺时针或逆时针的顺序给出两个正方形四个顶点的坐标,第一个正方形四边都平行于坐标轴,第二个正方形的四边与坐标轴夹角都是 ,问两个正方形是否相交(仅顶点有交点或者一个正方形包含于另一个正方形也属于相交)。
输入包含两行,每行四对整数,每对整数表示正方形的其中一个顶点的坐标,每一行的四个坐标都是按照顺时针或者逆时针顺序给出的。
第一行给出边与坐标轴平行的正方形顶点坐标,第二行给出边与坐标轴夹角为 的正方形顶点坐标,所有整数都在 内。
如果两个正方形相交则输出 "Yes",否则输出 "No",大小写任意。
| 输入 | 输出 |
|---|---|
| 0 0 6 0 6 6 0 6 1 3 3 5 5 3 3 1 |
YES |
| 0 0 6 0 6 6 0 6 7 3 9 5 11 3 9 1 |
NO |
| 6 0 6 6 0 6 0 0 7 4 4 7 7 10 10 7 |
YES |
先按照顶点给出的顺序在二维数组上描出正方形的边界,接着填充两个正方形内部,再判断是否相交。
#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <climits>#include <cstring>#include <string>#include <vector>#include <list>#include <queue>#include <stack>#include <map>#include <set>#include <bitset>#include <algorithm>#include <functional>#include <iomanip>using namespace std;#define LL long longconst int maxn = 200 + 100;int dx, dy;int x[8], y[8];bool vis[2][maxn][maxn];void pull(bool vis[maxn][maxn]) {for(int i = 0; i < 4; ++i) {int ii = (i + 1) % 4;dx = x[ii] - x[i];dy = y[ii] - y[i];if(dx != 0) {dx /= abs(dx);}if(dy != 0) {dy /= abs(dy);}int xx = x[i];int yy = y[i];while(yy != y[ii] || xx != x[ii]) {vis[xx][yy] = true;xx += dx;yy += dy;}vis[xx][yy] = true;}for(int i = 0; i < maxn; ++i) {int Left = maxn;int Right = 0;for(int j = 0; j < maxn; ++j) {if(vis[i][j]) {Left = min(Left, j);Right = max(Right, j);}}for(int j = Left; j <= Right; ++j) {vis[i][j] = true;}}}int main() {#ifdef LOCALfreopen("test.txt", "r", stdin);// freopen("test1.out", "w", stdout);#endif // LOCALios::sync_with_stdio(false);while(scanf("%d%d", &x[0], &y[0]) != EOF) {memset(vis, 0, sizeof(vis));x[0] += 100;y[0] += 100;for(int i = 1; i < 4; ++i) {scanf("%d%d", &x[i], &y[i]);x[i] += 100;y[i] += 100;}pull(vis[0]);for(int i = 0; i < 4; ++i) {scanf("%d%d", &x[i], &y[i]);x[i] += 100;y[i] += 100;}pull(vis[1]);bool flag = false;for(int i = 0; i < maxn; ++i) {for(int j = 0; j < maxn; ++j) {if(vis[0][i][j] && vis[1][i][j]) {flag = true;break;}}if(flag) {break;}}if(flag) {printf("YES\n");} else {printf("NO\n");}}return 0;}
两个人分别被分到一对数字,每个数字都在 内,且每对中的两个数字是不同的,两个人被分到的数字对保证只有一个数字是相同的,另一个数字不同。
现在第一个人给出 对数字,第二个人给出 对数字,他们给出的数字对中,必须有一个包含自己被分到的数字,其他数字对必须保证是两个不相同的在 内的数字。你不知道他们被分到的数字对是什么,但是可以看到他们给出的数字对,问你是否能判断出他们被分到的数字对中,相同的那个数字。
第一行包含 和 ,第二行包含 对数字,第三行包含 对数字。数据保证合法。
如果你可以猜到他们被分到的数字对中相同的那个数字,则输出这个数字,如果你猜不到,但是可以确定他们两个人都知道相同的那个数字,则输出 ,否则输出 。
| 输入 | 输出 |
|---|---|
| 2 2 1 2 3 4 1 5 3 4 |
1 |
| 2 2 1 2 3 4 1 5 6 4 |
0 |
| 2 3 1 2 4 5 1 2 1 3 2 3 |
-1 |
| 2 3 1 2 4 5 1 3 2 3 4 6 |
-1 |
按照题意模拟:先从第一个人的角度看,对于第一个人给出的每一对数字,如果对方给出的数字对中,与第一个人自己的数字对仅有一个数字相同,且相同的数字一样,则第一个人可以确定相同的数字,如:第一个人给出的是 ,对于第二个人给出的 ,他可以确定那个相同的数字是 ,但是对于第一个人来说,他知道自己那组数据是哪一组,从“你”的角度看,“你”不知道他给出的是哪组数据,如果假设第一个人拿到的是他展示的任一组数据,得到了多于 个的答案(如: 与 ,第一个人可以得到是 或者 中的一个答案,但是从“你”的角度看,却不知道是 还是 ),这时候就是输出 的情况。再用同样的逻辑从第二个人的角度看。注意只要有一个人无法唯一确定答案,就是输出 的情况,如样例 。
#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <climits>#include <cstring>#include <string>#include <vector>#include <list>#include <queue>#include <stack>#include <map>#include <set>#include <bitset>#include <algorithm>#include <functional>#include <iomanip>using namespace std;#define LL long longconst int maxn = 100;bool flag;int n[2];pair<int, int> par[2][maxn];set<int> st, stt;int match(const pair<int, int> &a, const pair<int, int> &b, int &num) {int ret = 0;if(a.first == b.first) {++ret;num = a.first;}if(a.second == b.second) {++ret;num = a.second;}if(a.first == b.second) {++ret;num = a.first;}if(a.second == b.first) {++ret;num = b.first;}return ret;}int main() {#ifdef LOCALfreopen("test.txt", "r", stdin);// freopen("test1.out", "w", stdout);#endif // LOCALios::sync_with_stdio(false);while(scanf("%d%d", &n[0], &n[1]) != EOF) {flag = true;st.clear();for(int i = 0; i < 2; ++i) {for(int j = 0; j < n[i]; ++j) {scanf("%d%d", &par[i][j].first, &par[i][j].second);}}for(int i = 0; i < 2; ++i) {int ii = 1 - i;for(int j = 0; j < n[i]; ++j) {stt.clear();for(int k = 0; k < n[ii]; ++k) {int num;int cnt = match(par[i][j], par[ii][k], num);if(cnt == 1) {st.insert(num);stt.insert(num);}}if((int)stt.size() > 1) {flag = false;}}}if(!flag) {printf("-1\n");continue;}if((int)st.size() != 1) {printf("0\n");} else {set<int>::iterator it = st.begin();printf("%d\n", *it);}}return 0;}
两个小飞船被两列大飞船包围,其中一列飞船的横坐标都是 ,另一列飞船的横坐标都是 ,它们的纵坐标都是整数,两个小飞船的横坐标都为 。
现在两列飞船同时向小飞船发射激光炮,小飞船拥有防护罩,激光炮无法伤害它们,但是激光会穿过他们射向对面的飞船,所有大飞船的两个激光炮都是瞄准两个小飞船发射的,问小飞船的纵坐标应该在哪个位置(不必为整数),才能使得被激光炮打中的大飞船最多,输出被打中的大飞船的最大数量。
第一行为 和 ,分别表示 和 的大飞船数量,第二行包含 个整数 ,表示 的飞船的纵坐标,第三行的 个整数 表示 的飞船的纵坐标,其中 。
能被击中的最多的大飞船数量。
| 输入 | 输出 |
|---|---|
| 3 9 1 2 3 1 2 3 7 8 9 11 12 13 |
9 |
| 5 5 1 2 3 4 5 1 2 3 4 5 |
10 |
由于两边飞船是对称分布的,所以小飞船的位置一定为整数或 ,所以可以将所有大飞船的纵坐标 ,所有坐标就都为整数了。
第一步预处理,先 计算出每个小飞船的纵坐标 ,对每个小飞船的纵坐标, 计算出当所有大飞船瞄准这个点时,左右两边的飞船被打中的状态(用 的 个 位记录被打中的状态),预处理时间复杂度为 。
接着 枚举小飞船的两个位置,对于每两个小飞船的位置,将两边的飞船击中状态按位或起来,用 计算总的被击落的飞船数,取最大值,总的时间复杂度为 。
#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <climits>#include <cstring>#include <string>#include <vector>#include <list>#include <queue>#include <stack>#include <map>#include <set>#include <bitset>#include <algorithm>#include <functional>#include <iomanip>using namespace std;#define LL long longconst int maxn = 200 + 100;int n, m, ans;int *it;int Left[maxn], Right[maxn];LL statu_Left[40000 + 100], statu_Right[40000 + 100];int Count(LL x) {int ret = 0;for(int i = 0; i < 62; ++i) {ret += ((x >> i) & 1);}return ret;}int main() {#ifdef LOCALfreopen("test.txt", "r", stdin);// freopen("test1.out", "w", stdout);#endif // LOCALios::sync_with_stdio(false);while(scanf("%d%d", &n, &m) != EOF) {ans = 0;for(int i = 0; i < n; ++i) {scanf("%d", &Left[i]);Left[i] *= 2;}for(int i = 0; i < m; ++i) {scanf("%d", &Right[i]);Right[i] *= 2;}sort(Left, Left + n);sort(Right, Right + m);for(int i = 0; i < n; ++i) {for(int j = 0; j < m; ++j) {int pos = (Left[i] + Right[j]) / 2;int Index = pos + 20000;statu_Left[Index] = statu_Right[Index] = 0;for(int k = 0; k < n; ++k) {int x = 2 * pos - Left[k];it = lower_bound(Right, Right + m, x);if(it - Right != m && *it == x) {statu_Left[Index] |= (1LL << k);}}for(int k = 0; k < m; ++k) {int x = 2 * pos - Right[k];it = lower_bound(Left, Left + n, x);if(it - Left != n && *it == x) {statu_Right[Index] |= (1LL << k);}}}}for(int a = 0; a < n; ++a) {for(int b = 0; b < m; ++b) {int pos1 = (Left[a] + Right[b]) / 2 + 20000;for(int c = 0; c < n; ++c) {for(int d = 0; d < m; ++d) {int pos2 = (Left[c] + Right[d]) / 2 + 20000;bitset<60> bit1(statu_Left[pos1] | statu_Left[pos2]);bitset<60> bit2(statu_Right[pos1] | statu_Right[pos2]);ans = max(ans, (int)(bit1.count() + bit2.count()));}}}}printf("%d\n", ans);}return 0;}