HDU 3484 Matrix Game 枚举暴力

上次周赛碰到这个题目,居然都没思路,真是不应该啊,起码也应该想到枚举法。

因为题目只允许每一row进行reverse操作,而每两列可以进行交换操作,所以首先把row的变化固定下来,即枚举第一列与第1-m列进行交换,之后逐个检查每一行第一列的状态 与 终态是否一致,不一致的话则该行就一定要进行reverse操作了,这样下来,每次枚举就把row的reverse变化给固定下来,接下来只要枚举 接下来的2-m行互相的列变换即可,只需一个嵌套循环即可,总的循环也只是三重 而n和m仅有100,规模承担的起

一个简单的枚举暴力题 虽然说还是带有一点技巧的,怎么比赛的时候就没想出来呢!!!

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int ma[105][105],tar[105][105],tmp[105][105];
int n,m;
void init()
{
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=m;j++)
            scanf("%d",&ma[i][j]);
    }
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=m;j++)
            scanf("%d",&tar[i][j]);
    }
}
void cpy(int c)
{
    for (int i=1;i<=m;i++)
    {
        for (int j=1;j<=n;j++)
        {
            tmp[j][i]=ma[j][i];
        }
    }
}
void change_col(int a,int b)
{
    for (int i=1;i<=n;i++)
    {
        int temp=tmp[i][a];
        tmp[i][a]=tmp[i][b];
        tmp[i][b]=temp;
    }
}
void change_row(int c)
{
    for (int i=1;i<=m;i++)
        tmp[c][i]^=1;
}
bool ok(int a,int b)
{
    for (int i=1;i<=n;i++)
    {
        if (tar[i][a]!=tmp[i][b])
            return false;
    }
    return true;
}
int main()
{
    while (scanf("%d%d",&n,&m))
    {
        if (n==-1) break;
        init();
        bool ans=0;
        for (int i=1;i<=m;i++)
        {
            cpy(i);
            change_col(1,i);
            for (int j=1;j<=n;j++)
            {
                if (tmp[j][1]!=tar[j][1])
                    change_row(j);
            }
            for (int j=2;j<=m;j++)
            {
                for (int k=j;k<=m;k++)
                {
                    ans=ok(j,k);
                    if (ans)
                    {
                        change_col(j,k);
                        break;
                    }
                }
            }
            if (ans) break;
        }
        if (ans) puts("Yes");
        else
            puts("No");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/kkrisen/p/3595377.html