aoj0525

一、题意:题目大致是讲一个烧饼铺烤烧饼,在一个n X m (1<=n<=10,1<=m<=10000)的烤桌上面摆着一堆烧饼,数字1表示烧饼正面,0表示烧饼反面。然后你每次可以将一整行或者一整列的烧饼翻面,即正面翻成反面或者反面翻成正面。但是必须是一整列或者一整行的翻,问最多可以使都少烧饼翻成正面?题意还是很好懂的。

二、思路:由于n比较小,所以可以对行DFS,那列呢?其实列很好处理,对每一列统计1的个数或者0的个数,保留最大者即是最大的正面个数,试想如果当前列正面个数多,那这一列就不翻面就好了,如果反面多,那么将该列翻面即可使得原先反面变成正面。所以对列直接统计即可。这题需要注意的是无论哪一行或者那一列先翻面都是无谓的,不影响结果,即翻面的顺序不影响结果,只考虑该行或该列是否要翻面即可,所以可以直接DFS。输入数据的第一行表示n和m,接下来的n X m的0和1的矩阵就表示当前烧饼状态,输入0 0结束。总而言之,此题很暴力。

三、代码:

#include"iostream"
#include"stdio.h"
#include"algorithm"
#include"vector"
#include"queue"
using namespace std;

int r,c;
int maze[15][10005];
int maxRes;

void Rev(int n)
{
    for(int j=0;j<c;j++)
        maze[n][j]=maze[n][j]^1;
}

int Cal()
{
    int sum=0;
    for(int j=0;j<c;j++)
    {
        int cnt=0;
        for(int i=0;i<r;i++)
        {
            cnt+=maze[i][j];
        }
        sum+=max(cnt,r-cnt);
    }
    return sum;
}

void Dfs(int n)
{
    if(n==r)
    {
        maxRes=max(maxRes,Cal());
        return;
    }
    Rev(n);
    Dfs(n+1);
    Rev(n);
    Dfs(n+1);
}

int main()
{
 //   freopen("in.txt","r",stdin);
    while(scanf("%d%d",&r,&c)==2,r&&c)
    {
        maxRes=0;
        for(int i=0;i<r;i++)
        {
            for(int j=0;j<c;j++)
                scanf("%d",&maze[i][j]);
        }
        Dfs(0);
        cout<<maxRes<<endl;
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/acm-jing/p/9606520.html