Wannafly挑战赛21 ABC

A 灯塔

题目描述

Z市是一座港口城市,来来往往的船只依靠灯塔指引方向。
在海平面上,存在n个灯塔。每个灯塔可以照亮以它的中心点为中心的90°范围。特別地, 由于特殊限制,每个灯塔照亮范围的角的两条边必须要么与坐标轴平行要么与坐标轴成45°。 由于经费限制,Z市的灯塔只能被点亮一座。你需要求出在这种情况下,是否存在一座灯塔能够照亮Z市的所有灯塔。

输入描述:

第一行一个整数T,表示数据组数。
对于每组数据,第一行一个整数n,表示灯塔的数量。
接下来n行,每行两个整数xi,yi,表示第i座灯塔的坐标点。

输出描述:

如果存在一座灯塔能够照亮Z市的所有灯塔则输出Yes,否则输出No(区分大小写)。
示例1

输入

复制
2
4
1 1
1 2
2 1
2 2
5
4 7
0 4
7 3
3 0
3 4

输出

复制
Yes
No

备注:

n≤1000000,T≤10,0≤|xi|,|yi|≤10^9


最边上的四个点来判断。
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e5+10;
 4 int x[N], y[N];
 5 bool flag[5];
 6 struct nod{
 7     int x, y;
 8 }e[N], e1[N];
 9 bool cmp1(const nod &a, const nod &b) {
10     return a.x < b.x;
11 }
12 bool cmp2(const nod &a, const nod &b) {
13     return a.y < b.y;
14 }
15 
16 int main() {
17     int n, t;
18     cin >> t;
19     while(t--) {
20         memset(flag, 1, sizeof(flag));
21         cin >> n;
22         for(int i = 0; i < n; i ++) scanf("%d%d", &e[i].x, &e[i].y), e1[i].x = e[i].x, e1[i].y = e[i].y;
23         sort(e,e+n,cmp1);
24         sort(e1,e1+n,cmp2);
25         if(e[0].y == e1[0].y || e[0].y == e1[n-1].y || e[n-1].x == e1[0].y || e[n-1].y == e1[n-1].y) {
26             printf("Yes\n");
27             continue;
28         }
29         if(e1[0].x == e[0].x || e1[0].x == e[n-1].x || e1[n-1].x == e[0].x || e1[n-1].x == e[n-1].x) {
30             printf("Yes\n");
31             continue;
32         }
33         for(int i = 0; i < n; i ++) {
34             if(abs(e[i].y-e[0].y) > abs(e[i].x-e[0].x)) flag[0] = 0;
35             if(abs(e[i].y-e[n-1].y) > abs(e[i].x-e[n-1].x)) flag[1] = 0;
36             if(abs(e[i].y-e1[0].y) < abs(e[i].x-e1[0].x)) flag[2] = 0;
37             if(abs(e[i].y-e1[n-1].y) < abs(e[i].x-e1[n-1].x)) flag[3] = 0;
38         }
39         if(flag[0] || flag[1] || flag[2] || flag[3]) printf("Yes\n");
40         else printf("No\n");
41     }
42     return 0;
43 }

 

 

B 机器人

题目描述

从前在月球上有一个机器人。
月球可以看作一个 n*m 的网格图,每个格子有三种可能:空地,障碍,机器人(有且仅有一个),现在地面指挥中心想让机器人在月球上行走,每次可以发送一个指令,为 U-往上走、D-往下走、L-往左走、R-往右走的其中之一。
当机器人接收到一个行走指令时,如果即将到达的位置为障碍物,那么机器人将留在原地,否则机器人向对应方向走一步,如果其走出边界那么立即死亡。
地面指挥中心当然不想让机器人就这么挂掉,因此其定义一个操作序列是安全的,当且仅当机器人按此操作序列走不会死亡。
但是从地球向月球发信息不是个容易的事,而且有时候某些指令还会在茫茫宇宙中被吞没,比如指挥中心传出去 RUR 指令,到机器人那里就可能变成 RR 或者变成 U,因此定义一个操作序列是绝对安全的当且仅当其任意子序列都是安全的。
现在地面指挥中心想知道,对于某一个地图,绝对安全的操作序列最长可以到多少,如果存在一个长度为正无穷的这样的序列,那么输出-1。

输入描述:

第一行一个正整数T,表示数据组数。
接下来一共 T 组数据,每组数据第一行有两个正整数 n,m,表示网格图的大小, 接下来 n 行,每行 m 个字符,表示这张网格图。
其中字符“.”表示空地,“#”表示障碍物,“S”表示机器人所在位置。

输出描述:

一共 T 行,每行一个整数,表示答案。
示例1

输入

复制
3
5 5
#####
#...#
.#S#.
#...#
#####
1 7
S......
5 8
#.######
#.#..S.#
#.#.##.#
#......#
########

输出

复制
-1
6
-1

备注:

数据范围 0≤T,n,m≤50


思考题吧,S的四个方向有一个#就是-1,否则就是n+m-2。
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 55;
 4 int t, n, m, x, y;
 5 char s[N][N];
 6 int main() {
 7     cin >> t;
 8     while(t--) {
 9         cin >> n >> m;
10         for(int i = 1; i <= n; i ++) cin >> s[i]+1;
11         for(int i = 1; i <= n; i ++) {
12             for(int j = 1; j <= m; j ++) {
13                 if(s[i][j] == 'S') {
14                     x = i, y = j;
15                 }
16             }
17         }
18         int mi = N, mx = 0, MI = N, MX = 0;
19         for(int i = 1; i <= n; i ++) {
20             if(s[i][y] == '#') {
21                 mi = min(mi, i);
22                 mx = max(mx, i);
23             }
24         }
25         for(int i = 1; i <= m; i ++) {
26             if(s[x][i] == '#') {
27                 MI = min(mi, i);
28                 MX = max(mx, i);
29             }
30         }
31         if(MI != N || mi != N || mx != 0 || MX != 0) {
32             printf("-1\n");
33         } else printf("%d\n",n+m-2 );
34     }
35     return 0;
36 }

 

C 大水题

题目描述

现在给你N个正整数ai,每个数给出一“好数程度” gi(数值相同但位置不同的数之间可能有不同的好数程度)。对于在 i 位置的数,如果有一在j位置的数满足 j < i 且 ai=aj,则你可以将位于[i,j]闭区间内的序列评为“好序列”,然后获得∑gk(j≤k≤i)(此闭区间内“好数程度”之和)分数。
注意: 在所有情况下,每个数都只能被一个”好序列”包含(只能与其他相应数被评为”好序列”一次);在符合要求的情况下,”好序列”的评定次数不受限制,且通过不同”好序列”获得的分数可以累加。

输入描述:

第一行有一个正整数N。接下来的一行有N个正整数ai,表示意义如上。(保证ai在32位整型范围内)接下来的一行有N个正整数gi,表示ai的”好数程度”。(保证gi在64位整型范围内)

输出描述:

一个整数,你可以获得的最大分数(通过不同”好序列”获得的分数可以累加),保证答案在64位整型范围内。
示例1

输入

复制
7
1 2 1 2 3 2 3
1 4 3 4 3 4 5

输出

复制
23

备注:

数据范围 2≤N≤300000

 

dp问题,dp[i] 表示从 1 至 i 用这 i 数的最大值是多少。mp[a[i]] 表示用a[i] 这个数,前面出现没有被选的数之和最小的数。

  1 #include <bits/stdc++.h>
 2 #define INF 0x3f3f3f3f
 3 #define ll long long
 4 using namespace std;
 5 const int N = 300010;
 6 ll a[N], sum[N], dp[N], n;
 7 map<ll, ll> mp;
 8 
 9 int main() {
10     cin >> n;
11     for(int i = 1; i <= n; i ++) cin >> a[i];
12     for(int i = 1; i <= n; i ++) cin >> sum[i], sum[i] += sum[i-1];
13     for(int i = 1; i <= n; i ++) {
14         if(!mp.count(a[i])) mp[a[i]] = INF;
15         dp[i] = max(dp[i-1], sum[i] - mp[a[i]]);
16         mp[a[i]] = min(mp[a[i]], sum[i-1]-dp[i-1]); 
17     }
18     cout << dp[n] << endl;
19     return 0;
20 }

 

 

posted @ 2018-08-05 13:55  starry_sky  阅读(309)  评论(0编辑  收藏  举报