Wannafly挑战赛21
链接:https://www.nowcoder.com/acm/contest/159/A
来源:牛客网
灯塔
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
题目描述:
Z市是一座港口城市,来来往往的船只依靠灯塔指引
在海平面上,存在n个灯塔。每个灯塔可以照亮以它的中心点为中心的90°范围。特別地, 由于特殊限制,每个灯塔照亮范围的角的两条边必须要么与坐标轴平行要么与坐标轴成45°。 由于经费限制,Z市的灯塔只能被点亮一座。你需要求出在这种情况下,是否存在一座灯塔能够照亮Z市
输入描述:
第一行一个整数T,表示数据组数。
对于每组数据,第一行一个整数n,表示灯塔的数量。
接下来n行,每行两个整数xi,yi
,表示第i座灯塔的坐标点。
输出描述:
如果存在一座灯塔能够照亮Z市的所有灯塔则输出Yes,否则输出No(区分大小写)。
备注:
n≤1000000,T≤10,0≤|xi|,|yi|≤10^9
找到最优策略,就是四个角,x最小,x最大,y最小,y最大.
1 #include <bits/stdc++.h> 2 #define N 1000005 3 #define inf 1000000000 4 using namespace std; 5 struct Node{ 6 int x,y; 7 }node[N]; 8 bool cmpx1(Node a,Node b){ 9 if(a.x == b.x){ 10 return a.y<b.y; 11 } 12 return a.x<b.x; 13 } 14 bool cmpy1(Node a,Node b){ 15 if(a.y == b.y){ 16 return a.x > b.x; 17 } 18 return a.y<b.y; 19 } 20 int t; 21 int main(){ 22 scanf("%d",&t); 23 while(t--){ 24 int x1 = inf,x2 = -inf,y1 = inf,y2 = -inf; 25 int n; 26 scanf("%d",&n); 27 bool prime = false; 28 for(int i=0;i<n;i++){ 29 scanf("%d%d",&node[i].x,&node[i].y); 30 x1 = min(x1,node[i].x);//x最小值 31 x2 = max(x2,node[i].x);//x最大值 32 y1 = min(y1,node[i].y);//y最小值 33 y2 = max(y2,node[i].y);//y最大值 34 } 35 sort(node,node+n,cmpx1);//x最小y最小 36 int xx = node[0].x,yy = node[0].y; 37 int xn = node[n-1].x,yn = node[n-1].y; 38 if((xx == x1&&yy == y1)||(xn == x2&&yn == y2)){ 39 prime = true; 40 }else{ 41 bool flag = true; 42 for(int i=0;i<n;i++){ 43 if(abs(node[i].y-yy)>abs(node[i].x-xx)){ 44 flag = false; 45 break; 46 } 47 } 48 if(flag) prime = true; 49 flag = true; 50 for(int i=0;i<n;i++){ 51 if(abs(node[i].y-yn)>abs(node[i].x-xn)){ 52 flag = false; 53 break; 54 } 55 } 56 if(flag) prime = true; 57 } 58 if(prime){ 59 cout<<"Yes"<<endl; 60 continue; 61 } 62 sort(node,node+n,cmpy1);//x最小y最大 63 xx = node[0].x,yy = node[0].y; 64 xn = node[n-1].x,yn = node[n-1].y; 65 if((xx == x2&&yy == y1)||(xn == x1&&yn == y2)){ 66 prime = true; 67 }else{ 68 bool flag = true; 69 for(int i=0;i<n;i++){ 70 if(abs(node[i].y-yy)<abs(node[i].x-xx)){ 71 flag = false; 72 break; 73 } 74 } 75 if(flag) prime = true; 76 flag = true; 77 for(int i=0;i<n;i++){ 78 if(abs(node[i].y-yn)<abs(node[i].x-xn)){ 79 flag = false; 80 break; 81 } 82 } 83 if(flag) prime = true; 84 } 85 if(prime){ 86 cout<<"Yes"<<endl; 87 }else{ 88 cout<<"No"<<endl; 89 } 90 } 91 return 0; 92 }
链接:https://www.nowcoder.com/acm/contest/159/B
来源:牛客网
机器人
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
题目描述
从前在月球上有一个机器人。
月球可以看作一个 n*m 的网格图,每个格子有三种可能:空地,障碍,机器人(有且仅有一个),现在地面指挥中心想让机器人在月球上行走,每次可以发送一个指令,为 U-往上走、D-往下走、L-往左走、R-往右走的其中之一。
当机器人接收到一个行走指令时,如果即将到达的位置为障碍物,那么机器人将留在原地,否则机器人向对应方向走一步,如果其走出边界那么立即死亡。
地面指挥中心当然不想让机器人就这么挂掉,因此其定义一个操作序列是安全的,当且仅当机器人按此操作序列走不会死亡。
但是从地球向月球发信息不是个容易的事,而且有时候某些指令还会在茫茫宇宙中被吞没,比如指挥中心传出去 RUR 指令,到机器人那里就可能变成 RR 或者变成 U,因此定义一个操作序列是绝对安全的当且仅当其任意子序列都是安全的。
现在地面指挥中心想知道,对于某一个地图,绝对安全的操作序列最长可以到多少,如果存在一个长度为正无穷的这样的序列,那么输出-1。
月球可以看作一个 n*m 的网格图,每个格子有三种可能:空地,障碍,机器人(有且仅有一个),现在地面指挥中心想让机器人在月球上行走,每次可以发送一个指令,为 U-往上走、D-往下走、L-往左走、R-往右走的其中之一。
当机器人接收到一个行走指令时,如果即将到达的位置为障碍物,那么机器人将留在原地,否则机器人向对应方向走一步,如果其走出边界那么立即死亡。
地面指挥中心当然不想让机器人就这么挂掉,因此其定义一个操作序列是安全的,当且仅当机器人按此操作序列走不会死亡。
但是从地球向月球发信息不是个容易的事,而且有时候某些指令还会在茫茫宇宙中被吞没,比如指挥中心传出去 RUR 指令,到机器人那里就可能变成 RR 或者变成 U,因此定义一个操作序列是绝对安全的当且仅当其任意子序列都是安全的。
现在地面指挥中心想知道,对于某一个地图,绝对安全的操作序列最长可以到多少,如果存在一个长度为正无穷的这样的序列,那么输出-1。
输入描述:
第一行一个正整数T,表示数据组数。
接下来一共 T 组数据,每组数据第一行有两个正整数 n,m,表示网格图的大小, 接下来 n 行,每行 m 个字符,表示这张网格图。
其中字符“.”表示空地,“#”表示障碍物,“S”表示机器人所在位置。
输出描述:
一共 T 行,每行一个整数,表示答案。
示例1
备注:
数据范围 0≤T,n,m≤50
这算是一个理解题,只要分析出来了,就能直接A.
1 #include <bits/stdc++.h> 2 using namespace std; 3 int dis[4][2]={0,1,0,-1,-1,0,1,0}; 4 int t; 5 char s[55][55]; 6 int main(){ 7 cin>>t; 8 while(t--){ 9 memset(s,0,sizeof(s)); 10 int x,y; 11 int xx,yy; 12 cin>>x>>y; 13 for(int i=0;i<x;i++){ 14 for(int j = 0;j<y;j++){ 15 cin>>s[i][j]; 16 if(s[i][j]=='S'){ 17 xx = i,yy = j; 18 } 19 } 20 } 21 bool prime = true; 22 for(int i=0;i<4;i++){ 23 int x1 = xx,y1 = yy; 24 for(int j= 0;x1>=0&&x1<x&&y1>=0&&y1<y;j++){ 25 x1 += dis[i][0]; 26 y1 += dis[i][1]; 27 if(s[x1][y1]=='#'){ 28 prime = false; 29 break; 30 } 31 } 32 if(!prime) break; 33 } 34 if(prime){ 35 cout<<x+y-2<<endl; 36 }else{ 37 cout<<"-1"<<endl; 38 } 39 } 40 return 0; 41 }
链接:https://www.nowcoder.com/acm/contest/159/C
来源:牛客网
大水题
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
题目描述
现在给你N个正整数ai,每个数给出一“好数程度” gi(数值相同但位置不同的数之间可能有不同的好数程度)。对于在 i 位置的数,如果有一在j位置的数满足 j < i 且 ai=aj,则你可以将位于[i,j]闭区间内的序列评为“好序列”,然后获得∑gk(j≤k≤i)(此闭区间内“好数程度”之和)分数。
注意: 在所有情况下,每个数都只能被一个”好序列”包含(只能与其他相应数被评为”好序列”一次);在符合要求的情况下,”好序列”的评定次数不受限制,且通过不同”好序列”获得的分数可以累加。输入描述:
第一行有一个正整数N。i
接下来的一行有N个正整数a
,表示意义如上。i
(保证a
在32位整型范围内)i
接下来的一行有N个正整数g
,表示ai
的”好数程度”。i
(保证g
在64位整型范围内)
输出描述:
一个整数,你可以获得的最大分数(通过不同”好序列”获得的分数可以累加),保证答案在64位整型范围内。
备注:
数据范围 2≤N≤300000
题目叫大水题,但是我没写出来.(哭死)
赛后补题看了一下别人的思路,dp,加上前缀和就行.
1 #include <bits/stdc++.h> 2 #define N 300005 3 #define ll long long int 4 using namespace std; 5 6 ll a[N],b[N],dp[N][2]; 7 map<ll,ll> mp; 8 9 int main(){ 10 int n; 11 cin>>n; 12 for(int i=1;i<=n;i++){ 13 cin>>a[i]; 14 } 15 for(int i=1;i<=n;i++){ 16 cin>>b[i]; 17 b[i] += b[i-1]; 18 } 19 for(int i=1;i<=n;i++){ 20 ll ans; 21 if(mp.count(a[i])) 22 ans = mp[a[i]]; 23 else ans = 0; 24 if(ans){ 25 dp[i][1] = max(dp[ans][1]+b[i]-b[ans],dp[ans][0]+b[i]-b[ans-1]); 26 } 27 dp[i][0] = max(dp[i-1][0],dp[i-1][1]); 28 mp[a[i]] = i; 29 } 30 cout<<max(dp[n][0],dp[n][1])<<endl; 31 return 0; 32 }