codeforces 425B Sereja and Table (枚举、位图)

输入n*m的01矩阵、以及k。

n,m<=100,k<=10

问修改至多k个,使得矩阵内的各连通块(连着的0或1构成连通块)都是矩形,且不含另外的数字(边界为0(1)的矩形内不含1(0)),求最少修改个数。

 

再次感觉以前见过类似的。。。。完全不会。。。

看了题解再看别人的代码才搞懂。。。。

首先,要知道一个结论,满足题意的矩阵,任意2行(列)的抑或值必须为全0或全1。

然后,分类讨论,

如果可以修改个数k<n,如果有答案,那必然至少有一行是没修改的,枚举不修改的行,统计。

k>=n的时候,必然有n,m<=10,这时候可能每一行都有修改,故枚举标准列的情况,即int i=0;i<(1<<n);++i,统计。

复杂度应该是,max(100^3, 100*10*2^10)=10^6

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <string>
 7 #include <vector>
 8 #include <queue>
 9 #include <set>
10 using namespace std;
11 
12 #define ll long long
13 #define inf 0x3f3f3f3f
14 #define eps 1e-8
15 
16 int a[110][110];
17 int main(){
18     int n,m,k;
19     while(~scanf("%d%d%d",&n,&m,&k)){
20         for(int i=0;i<n;++i)for(int j=0;j<m;++j)scanf("%d",a[i]+j);
21         int ans=k+1;
22         if(k<n){
23             for(int i=0;i<n;++i){
24                 int tmp=0;
25                 for(int j=0;j<n;++j){
26                     int dis=0;
27                     for(int k=0;k<m;++k)
28                         dis+=(a[i][k]^a[j][k]);
29                     tmp+=min(dis,m-dis);
30                 }
31                 ans=min(ans,tmp);
32             }
33         }
34         else {
35             for(int i=(1<<n)-1;i>=0;--i){
36                 int tmp=0;
37                 for(int j=0;j<m;++j){
38                     int dis=0;
39                     for(int k=0;k<n;++k)
40                         if((i&(1<<k))==(a[k][j]<<k))
41                             dis++;
42                     tmp+=min(dis,n-dis);
43                 }
44                 ans=min(ans,tmp);
45             }
46         }
47         if(ans==k+1)puts("-1");
48         else printf("%d
",ans);
49     }
50     return 0;
51 }
View Code
原文地址:https://www.cnblogs.com/nextbin/p/3696678.html