CF#648(Div.2) A-D
第一次做CF,只做出来4道,时间还是蛮紧张的。
A.签到题
去掉所有有数字的行和列,取剩余行和列中较小的,若为奇数则先手胜,反之后手胜
B.排序
给定一个数组,每个数都有对应标签0或1,只有标签不同的两个数才能交换,问能否让数组从小到大排列。
如果有至少1个0,那么任意1都能随意交换。同理有1个1任意0都能随意交换。考虑其余的特殊情况即可。
C.数组
给定两个1-n的序列,请你旋转下方的序列,使相同位置相同数的数量最多。
记一下每个数之间的位置差,找差最大的。
D.搜索
给定一个迷宫,内有墙,好人和坏人。能否在空地上加墙使得好人能到右下角而坏人不能。
考虑坏人的上下左右。如果任何一个好人都不必经过这四个格子,那么把它用墙封起来也无所谓。如果存在一个好人必须经过这个格子,那么坏人也可以走入这个格子然后走那个好人的路线到终点,这时这个格子的效果和墙是一样的。
因此首先封死坏人的上下左右,然后搜索。注意如果坏人四周不要无脑变墙,别把坏人和好人也变墙了。因为数据范围太小了干脆没有用搜索而是用暴力。
#include<stdio.h> int main() { int t,m,n,add,add2,x,y,add3; scanf("%d",&t); char q[52][52],c;//0-51 0和51为边界 while(t--) { for(add=0;add<52;add++) { for(add2=0;add2<52;add2++) { q[add][add2]='#'; } } scanf("%d %d",&n,&m); for(add=1;add<=n;add++) { c=getchar(); for(add2=1;add2<=m;add2++) { q[add][add2]=getchar(); } } //scanf("%d %d",&x,&y); x=n,y=m; for(add=1;add<=n;add++) { for(add2=1;add2<=m;add2++) { if(q[add][add2]=='B') { if(q[add+1][add2]=='G'||q[add-1][add2]=='G'|| q[add][add2+1]=='G'||q[add][add2-1]=='G') break; if(q[add+1][add2]!='B') q[add+1][add2]='#'; if(q[add-1][add2]!='B') q[add-1][add2]='#'; if(q[add][add2+1]!='B') q[add][add2+1]='#'; if(q[add][add2-1]!='B') q[add][add2-1]='#'; } } if(add2!=m+1) break; } if(add!=n+1) { printf("No\n"); continue; } if(q[x][y]=='#') { for(add=1;add<=n;add++) { for(add2=1;add2<=m;add2++) { if(q[add][add2]=='G') break; } if(add2!=m+1) break; } if(add!=n+1) { printf("No\n"); continue; } } q[x][y]='S'; for(add3=0;add3<=n*m;add3++) { for(add=1;add<=n;add++) { for(add2=1;add2<=m;add2++) { if(q[add][add2]=='S') { if(q[add+1][add2]!='#') q[add+1][add2]='S'; if(q[add-1][add2]!='#') q[add-1][add2]='S'; if(q[add][add2+1]!='#') q[add][add2+1]='S'; if(q[add][add2-1]!='#') q[add][add2-1]='S'; } } } } for(add=1;add<=n;add++) { for(add2=1;add2<=m;add2++) { if(q[add][add2]=='G') break; } if(add2!=m+1) break; } if(add!=n+1) printf("No\n"); else printf("Yes\n"); /*printf("\n--------\n"); for(add=0;add<=n+1;add++) { for(add2=0;add2<=m+1;add2++) { printf("%c",q[add][add2]); } printf("\n"); } printf("--------\n");*/ } return 0; }