codeforces 425B Sereja and Table(状态压缩,也可以数组模拟)

题目

给出一个n*m的01矩阵, 让你最多改变k个里面的值(0变1,1变0), 使得0、1的连通分量是矩阵。输出最少步数

1 ≤ n, m ≤ 100; 1 ≤ k ≤ 10

题解:

如果01连通分量是矩形,

那么矩形一定是这样的:

0101010

1010101

0101010

1010101

(上面的01代表子矩阵块)。

也就是每一行要么是相同,要么是相反的。

如果n>k, 肯定有一行是不能改变的,那么枚举这一行,然后其余的要么变相同,要么变相反,看最少的步数。

如果n<k ,那么可以枚举第一列的状态(2^k), 然后其余列变成和第一列相同或者相反。

以上引用自:http://www.cnblogs.com/kuangbin/p/3702113.html

//我不知道我这种模拟算不算是状态压缩

#include <cstdio>
#include<iostream>
#include <cstring>
#include <algorithm>
#include<vector>
using namespace std;
int k,n,m;
int a[110][110];

int min(int x,int y)
{
    if(x<y)return x;
    return y;
}

int meijuh()
{
    int minn=210000000;
    for(int i=0;i<k+1;i++)
    {
        int ans=0;
        for(int ii=0;ii<n;ii++)
        {
            if(i!=ii)
            {
                int sa=0,di=0;
                for(int j=0;j<m;j++)
                {
                    if(a[i][j]==a[ii][j])
                        sa++;
                    else
                        di++;
                }
                ans+=min(sa,di);
            }
        }
        minn=min(minn,ans);
    }
    return minn;
}
int meijul()
{
    int er[2048][11];
    for(int i=0;i<2048;i++)er[i][0]=i&1;
    for(int i=0;i<1024;i++)for(int j=0;j<2;j++)er[i*2+j][1]=i&1;
    for(int i=0;i<512;i++)for(int j=0;j<4;j++)er[i*4+j][2]=i&1;
    for(int i=0;i<256;i++)for(int j=0;j<8;j++)er[i*8+j][3]=i&1;
    for(int i=0;i<128;i++)for(int j=0;j<16;j++)er[i*16+j][4]=i&1;
    for(int i=0;i<64;i++)for(int j=0;j<32;j++)er[i*32+j][5]=i&1;
    for(int i=0;i<32;i++)for(int j=0;j<64;j++)er[i*64+j][6]=i&1;
    for(int i=0;i<16;i++)for(int j=0;j<128;j++)er[i*128+j][7]=i&1;
    for(int i=0;i<8;i++)for(int j=0;j<256;j++)er[i*256+j][8]=i&1;
    for(int i=0;i<4;i++)for(int j=0;j<512;j++)er[i*512+j][9]=i&1;
    for(int i=0;i<2;i++)for(int j=0;j<1024;j++)er[i*1024+j][10]=i&1;

    int minn=210000000;
    for(int i=0;i<(1<<n);i++)
    {
        int ans=0;
        for(int j=0;j<m;j++)
        {
            int sa=0,di=0;
            for(int ii=0;ii<n;ii++)
            {
                if(er[i][ii]==a[ii][j])
                    sa++;
                else di++;
            }
            ans=ans+min(sa,di);
        }
        minn=min(minn,ans);
    }
    return minn;
}

int main() {

    cin >>n>>m>>k;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            cin >>a[i][j];
    int minn=210000000;
    if(n>k)
    {
        minn = meijuh();
    }
    else
    {
        minn=meijul();
    }
    if(minn<=k)
        cout << minn<<endl;
    else
        cout <<-1<<endl;
    return 0;
}

codeforces 425B Sereja and Table(状态压缩,也可以数组模拟)

时间: 2024-12-25 10:45:19

codeforces 425B Sereja and Table(状态压缩,也可以数组模拟)的相关文章

CodeForces 425B Sereja and Table

题意: 一个充满0和1的矩形  最多将k个数字翻转  问  最少翻转几个数字可以使所有0或1的连通块都是矩形  如果不可能输出-1 思路: 首先  如果确定了一行  那么整个矩形就确定了 因为在最后的状态中  每一行要么与确定的行完全一致  要么完全相反  这才能保证连通块都是矩形 然后  本题k很小  因此可以分类讨论 如果 max(n,m)<=k 那么可以暴力枚举第一行状态  进而计算翻转次数  最多只有2^10种情况 否则 max(n,m)>k  那么至少有一行或者一列是没有被修改的  

[CodeForces 11D] A Simple Task - 状态压缩入门

状态压缩/Bitmask 在动态规划问题中,我们会遇到需要记录一个节点是否被占用/是否到达过的情况.而对于一个节点数有多个甚至十几个的问题,开一个巨型的[0/1]数组显然不现实.于是就引入了状态压缩,用一个整数的不同二进制位来表示该节点的状态. Description Given a simple graph, output the number of simple cycles in it. A simple cycle is a cycle with no repeated vertices

Codeforces 580D Kefa and Dishes(状态压缩DP)

题目链接:http://codeforces.com/problemset/problem/580/D 题目大意:有n盘菜每个菜都有一个满意度,k个规则,每个规则由x y c组成,表示如果再y之前吃x那么满意度会额外增加c,现在凯迪想吃m盘菜,并且满意度最大,请求出满意度.解题思路:状压DP,设dp[i][j]表示在状态i并且最后一道菜放在位置j时的最大满意度.注意要处理好一道菜时的情况,以及注意二进制表示中1的个数超过m的情况. 代码: 1 #include<bits/stdc++.h> 2

Codeforces Round #108 (Div. 2)——状态压缩DP+spfa+dfs——Garden

Vasya has a very beautiful country garden that can be represented as an n × m rectangular field divided into n·m squares. One beautiful day Vasya remembered that he needs to pave roads between k important squares that contain buildings. To pave a roa

CodeForces 380C Sereja and Brackets(扫描线+树状数组)

[题目链接] http://codeforces.com/problemset/problem/380/C [题目大意] 给出一个括号序列,求区间内左右括号匹配的个数. [题解] 我们发现对于每个右括号,其匹配的左括号是固定的, 我们保存每个右括号匹配的左括号位置, 对区间询问进行线扫描,将扫描的区间右端点及其之前所有的右括号对应的左括号位置做标记, 只要查询询问区间的标记个数就是答案,这个可以用树状数组维护. [代码] #include <cstdio> #include <algor

poj 2441 Arrange the Bulls (状态压缩dp+滚动数组)

题意: n头牛和m个barn,每头牛有自己喜欢的p个barn(1<=p<=m),问有多少种安排n头牛的方法. 分析: dp[i][j]表示i头牛在j状态下的方法数. dp[i][j] = sigma(dp[i-1][k])  (k从0到 1<<m). 要用滚动数组优化,否则dp[20][1<<20]会MLE! 注意滚动数组的清空= =! 1 #include<stdio.h> 2 #include<cstring> 3 #include<i

Codeforces Beta Round #85 (Div. 1 Only) C (状态压缩或是数学?)

C. Petya and Spiders Little Petya loves training spiders. Petya has a board n × m in size. Each cell of the board initially has a spider sitting on it. After one second Petya chooses a certain action for each spider, and all of them humbly perform it

codeforces B - Preparing Olympiad(dfs或者状态压缩枚举)

B. Preparing Olympiad You have n problems. You have estimated the difficulty of the i-th one as integer ci. Now you want to prepare a problemset for a contest, using some of the problems you've made. A problemset for the contest must consist of at le

(并查集\状态压缩)CodeForces - 469D Two Sets

Little X has n distinct integers: p1,?p2,?...,?pn. He wants to divide all of them into two sets A and B. The following two conditions must be satisfied: If number x belongs to set A, then number a?-?x must also belong to set A. If number x belongs to