回文矩阵 51Nod - 1316

https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1316

数据量很小 可以先暴力枚举出r行c列 然后求出使当前这r行c列回文的代价 取个最小值即可

对于(i,j)这个位置 (i,m-j-1) (n-i-1,j) (n-i-1,m-j-1)这三个位置只要出现在了r行c列里 就必须和(i,j)一致 并且和其他位置无关 先扫一遍矩阵 并查集处理出所有这些集合 对每个集合看0多还是1多

智障啊 以为是n*n的矩阵 WA到死

#include <bits/stdc++.h>
using namespace std;
const int N=0x3f3f3f3f;

int flagr[10][10],flagc[10][10];
int row[10],col[10],f[100],cnt0[100],cnt1[100];
int r,c,n,m,ans;
char ch[10][10];

int getf(int p)
{
    if(f[p]==p) return p;
    else return f[p]=getf(f[p]);
}

void unite(int u,int v)
{
    int fu,fv;
    fu=getf(u),fv=getf(v);
    if(fu!=fv)
    {
        f[fv]=fu;
        cnt0[fu]+=cnt0[fv];
        cnt1[fu]+=cnt1[fv];
    }
}

int id(int i,int j)
{
    return i*m+j;
}

void solve()
{
    int i,j,sum,v0,v1;

    memset(flagr,0,sizeof(flagr));
    memset(flagc,0,sizeof(flagc));
    for(i=0;i<r;i++) for(j=0;j<m;j++) flagr[row[i]][j]=1;
    for(i=0;i<n;i++) for(j=0;j<c;j++) flagc[i][col[j]]=1;
    for(i=0;i<n;i++)
    {
        for(j=0;j<m;j++)
        {
            if(flagr[i][j]||flagc[i][j])
            {
                f[id(i,j)]=id(i,j);
                if(ch[i][j]=='0') cnt0[id(i,j)]=1,cnt1[id(i,j)]=0;
                else cnt0[id(i,j)]=0,cnt1[id(i,j)]=1;
            }
        }
    }

    for(i=0;i<n;i++)
    {
        for(j=0;j<m;j++)
        {
            if(flagr[i][j]) unite(id(i,j),id(i,m-j-1));
            if(flagc[i][j]) unite(id(i,j),id(n-i-1,j));
        }
    }

    sum=0;
    for(i=0;i<n;i++)
    {
        for(j=0;j<m;j++)
        {
            if((flagr[i][j]||flagc[i][j])&&f[id(i,j)]==id(i,j))
            {
                sum+=min(cnt0[id(i,j)],cnt1[id(i,j)]);
            }
        }
    }

    ans=min(ans,sum);
}

void dfsII(int cnt,int pre)
{
    int i;
    if(cnt==c)
    {
        solve();
        return;
    }
    for(i=pre+1;i<m;i++)
    {
        col[cnt]=i;
        dfsII(cnt+1,i);
    }
}

void dfsI(int cnt,int pre)
{
    int i;
    if(cnt==r)
    {
        dfsII(0,-1);
        return;
    }
    for(i=pre+1;i<n;i++)
    {
        row[cnt]=i;
        dfsI(cnt+1,i);
    }
}

int main()
{
    int i,j;
    scanf("%d%d%d",&r,&c,&n);
    for(i=0;i<n;i++) scanf("%s",ch[i]);
    m=strlen(ch[0]);
    ans=N;
    dfsI(0,-1);
    printf("%d\n",ans);
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值