51NOD 1316 回文矩阵 【枚举】

来源:互联网 发布:武汉大学网络教学平台 编辑:程序博客网 时间:2024/06/05 02:25
1316 回文矩阵题目来源: TopCoder基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 收藏  关注 一个N*M的矩阵A完全由01两个数字组成(0<N,M<=8),矩阵第i行第j列上的项为A[i][j],i与j从0标起,即0<=i<N,0<=j<M。现在存在两种操作:(1)将矩阵中的任一项A[i][j]改为数字1;(2)将矩阵中的任一项A[i][j]改为数字0;现在给出初始的矩阵A,要求经过最少次操作,使矩阵A中至少有RowCount行是回文的,同时存在至少ColumCount列是回文的。输出这个最少操作的次数。矩阵中第r行是回文的,指序列{A[r][0],A[r][1],...A[r][M-1]}回文,即所有的 i 有A[r][i]=A[r][M-1-i];矩阵中第c列是回文的,指序列{A[0][c],A[1][c],...A[N-1][c]}回文,即所有的 i 有A[i][c]=A[N-1-i][c].例如4x4的矩阵如下:0000100011001110要求RowCount = 2,且ColumCount = 2.可以将A[3][0]改为0,使第0行与第3行回文,同时第0列与第3列回文。变化后如下:0000100011000110Input第一行两个正整数,表示RowCount,ColumCount,且0<=RowCount<=N,0<=ColumCount<=M.第二行一个整数N,即矩阵的行数,1<=N<=8.之后有N行,每行一个由M个‘0’、‘1’字符构成的字符串,表示N*M矩阵的信息。Output一个整数,表示最少操作的次数。Input示例2 240000100011001110Output示例1孔炤 (题目提供者)

枚举出是回文的r行和c列
确定A[i][j],如果i行是回文 A[i][m-j-1]=A[i][j]
j列是回文 A[n-i-1][j]=A[i][j]
n-i-1行是回文 A[n-i-1][m-j-1]=A[i][j]…

遍历i,j 选出A[i][j]能确定的位置,并确定最小需要多少次改变操作即可

O(CrnCcmnm)

#include<stdio.h>#include <bits/stdc++.h>#define ll long long#define pii pair<int,int>#define MEM(a,x) memset(a,x,sizeof(a))using namespace std;const int inf=1e9+7;char str[8][9];bool vis[8][8];int n,m;vector<pii>vec;inline int bits(int x){//x含有多少个1    int ans=0;    while(x){        ans+=(x&1);        x>>=1;    }    return ans;}int f(int i,int j,int x,int y){//a[i][j]能确定的位置,至少多少次操作使得他们值全部一样    vec.clear();    vec.push_back({i,j});    int ii=n-i-1,jj=m-j-1;    bool flag=false;    if((1<<i)&x){        vec.push_back({i,jj});        if((1<<jj)&y){            vec.push_back({ii,jj});            flag=true;        }    }    if((1<<j)&y){        vec.push_back({ii,j});        if(!flag){            if((1<<ii)&x){                vec.push_back({ii,jj});            }        }    }    int ans=inf;    for(char k='0';k<='1';++k){        int sum=0;        for(int z=0;z<vec.size();++z){            int i=vec[z].first,j=vec[z].second;            sum+=abs(k-str[i][j]);        }        ans=min(ans,sum);    }    for(int z=0;z<vec.size();++z){        int i=vec[z].first,j=vec[z].second;        vis[i][j]=true;    }    return ans;}int check(int x,int y){    MEM(vis,0);    int ans=0;    for(int i=0;i<n;++i){        for(int j=0;j<m;++j){            if(vis[i][j]){                continue;            }            ans+=f(i,j,x,y);        }    }    return ans;}int slove(int r,int c){    int ans=64;    for(int i=0,endI=(1<<n);i<endI;++i){        if(bits(i)==r){            for(int j=0,endJ=(1<<m);j<endJ;++j){                if(bits(j)==c){                    ans=min(ans,check(i,j));                }            }        }    }    return ans;}int main(){    //freopen("/home/lu/code/r.txt","r",stdin);    int r,c;    while(~scanf("%d%d",&r,&c)){        scanf("%d",&n);        for(int i=0;i<n;++i){            scanf("%s",str[i]);        }        m=strlen(str[0]);        printf("%d\n",slove(r,c));    }    return 0;}