【NOIP模拟赛】队列变换
作者:互联网
---恢复内容开始---
题目描述
有一个调皮的班级,他们上体育课,现在排成了n行n列的一个矩形。每个人却不是面向老师,而是面向左侧或右侧。例如:
RLR
RRL
LLR
因为老师是新来的,所以还叫不出学生的名字。他每次都是朝着一列或一行喊:向后转。这一行或这一列的L就全部变成R,R就全部变成L。因为不能让所有学生都朝一个方向,所以体育老师退而求其次,他可以允许一个人和其他人方向相反。体育老师的指令没有次数限制,他也可以对同一行或同一列进行多次发令。请找出这样的一个学生。如果最后无法使得只有一个学生和其他人方向相反,则输出“-1”。如果存在方案,则输出那一个学生的行号和列号(均从1开始)。如果有多种方案,则输出行号最小的那一个学生,如果多个学生的行坐标相等,则输出列号最小的那一个。
输入
输入文件名为 transitioning.in。
第一行一个整数,表示n。
接下来是n行,每行n个字符,每一个字符为L或R。
输出
输出文件名为 transitioning.out。
输出文件只有 1 行,表示那个讨厌的学生的行号和列号。
如果没有,则输出-1。
样例输入 Copy
3 RLR RRL LLR
样例输出 Copy
1 1
一道用了一定贪心策略的一道题。我们不必想着要把队伍尽量统一。从样例看,将给出图无论调整为R还是L,剩下的人都是1 1.也就是说,
如果能将队伍调整为只有一个人为R,其余人都为L,那么也可以将队伍调整为只有一个人为L,其余人为R。所以,我们只考虑一种情形,就是将队伍全部调整为L,除了一个人为R。
这样我们就只需要讨论一种情况了。这应该不属于贪心算法,而是贪心的一种思维。所以紧接着题目要求“坏学生”尽量出现在前面,所以我们从下往上,从右往左调整,这也是贪心的思维。
例如从最后一行开始,我们采用“列取反”的操作,最后一行全变成L。需要注意的是最后一行“列取反”后,其他行就不能再这样了,因为这会导致其他行后面的行又混乱。
从下到上依次考虑其他的行,看每一行的较少的字符是不是等于1个。(这里不要求较少的字符一定是L,因为可以对该行取反)如果是,那么它就是那一个学生的位置。如果该行较少的字符出现了两个,或者有两行以上都出现了不一致,或者所有行都是一致的,这都要输出-1了。
同理,从最后一列开始操作也是可行的,这里就不再赘述了。
附上代码
#include<bits/stdc++.h> using namespace std; #define MAXN 1005 int n; char s[MAXN][MAXN]; int cnt[MAXN]; int ansx,ansy,cntR; int cntx,miny1,miny2; int main() { //freopen("transitioning.in","r",stdin); //freopen("transitioning.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%s",s[i]+1); for(int j=1;j<=n;j++) { if(s[n][j]=='R') cnt[j]^=1; } for(int i=n-1;i>=1;i--) { cntR=0; for(int j=n;j>=1;j--) if(s[i][j]=='R'&&cnt[j]==0||s[i][j]=='L'&&cnt[j]==1) cntR++,miny1=j; else miny2=j; if(cntR==0||cntR==n) continue; else { if(min(n-cntR,cntR)==1) { if(cntx>0) { printf("-1\n"); return 0; } else { ansx=i; if(cntR==1)ansy=miny1; else ansy=miny2; cntx++; } } else { printf("-1\n"); return 0; } } } if(ansx==0&&ansy==0) printf("-1\n"); else printf("%d %d\n",ansx,ansy); return 0; }View Code
新人博主,还望多多关照!
标签:输出,NOIP,ansy,队列,else,变换,int,cntR,学生 来源: https://www.cnblogs.com/Enderman/p/11362495.html