【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

新人博主,还望多多关照!

猜你喜欢

转载自www.cnblogs.com/Enderman/p/11362495.html