USACO 2019 US Open Contest, Silver Problem 1. Left Out —— 棋盘翻转

This way

题意:

给你n*n的矩阵,每个位置都有一头牛,它们要么面朝左边要么面朝右边,你可以同时改变一行或者一列的牛的朝向。最后如果只有一头牛的朝向是反的,那么输出它的坐标,如果有多种情况,以行为第一关键字,列为第二关键字。

题解:

第一行如果有某一列的数是-1,翻转这列。之后如果第一列的某一行是-1,翻转这一行。这样第一列与第一行都是0.然后我们发现,无论怎么翻转,在保证第一行和第一列的前提下得出来的结果就是这个矩阵。所以我们假设第一行是正确的,如果2-n行到2-n列所有数都是1,那么证明第一行第一个点是错误的,所以答案是1,1。那么还有两种特殊情况:第一行某一列是错误的或者第一列某一行是错误的,那么我们查找每一行是否有n-1个1,或者某一列是否有n-1个1,除了这两种情况,剩下的只有某一个点是错误的。其它情况就不可能了。

#include
using namespace std;
const int N=1e3+5;
int mp[N][N];
char s[N];
int cal(int l,int r,int d,int u,int t)
{
    int ans=0;
    for(int i=l;i<=r;i++)
        for(int j=d;j<=u;j++)
            ans+=mp[i][j]==t;
    return ans;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",s+1);
        for(int j=1;j<=n;j++)
            mp[i][j]=s[j]=='L';
    }
    for(int i=1;i<=n;i++)
    {
        if(mp[1][i]==1)
            for(int j=1;j<=n;j++)
                mp[j][i]^=1;
    }
    for(int i=1;i<=n;i++)
    {
        if(mp[i][1]==1)
            for(int j=1;j<=n;j++)
                mp[i][j]^=1;
    }
    if(cal(2,n,2,n,0)==0)
        return 0*printf("1 1\n");
    if(cal(2,n,2,n,1)==1)
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(mp[i][j]==1)
                    return 0*printf("%d %d\n",i,j);
    }
    else
    {
        if(cal(2,n,2,n,1)==n-1)
        {
            for(int i=2;i<=n;i++)
                if(cal(2,n,i,i,1)==n-1)
                    return 0*printf("1 %d\n",i);
            for(int i=2;i<=n;i++)
                if(cal(i,i,2,n,1)==n-1)
                    return 0*printf("%d 1\n",i);
            return 0*printf("-1\n");
        }
        else
            return 0*printf("-1\n");
    }
}

你可能感兴趣的:(想法)