CodeForces 425B Sereja and Table

题意:

一个充满0和1的矩形  最多将k个数字翻转  问  最少翻转几个数字可以使所有0或1的连通块都是矩形  如果不可能输出-1

思路:

首先  如果确定了一行  那么整个矩形就确定了

因为在最后的状态中  每一行要么与确定的行完全一致  要么完全相反  这才能保证连通块都是矩形

然后  本题k很小  因此可以分类讨论

如果 max(n,m)<=k 那么可以暴力枚举第一行状态  进而计算翻转次数  最多只有2^10种情况

否则 max(n,m)>k  那么至少有一行或者一列是没有被修改的  那么可以枚举哪一行没被修改  再计算翻转次数

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 110

int a[N][N];
int n,m,t,tmp,ans,sum;

int main()
{
    int i,j,k;
    scanf("%d%d%d",&n,&m,&t);
    for(i=1;i<=n;i++) for(j=1;j<=m;j++) scanf("%d",&a[i][j]);
    if(n<m)
    {
        for(i=1;i<=m;i++)
        {
            for(j=i+1;j<=m;j++) swap(a[i][j],a[j][i]);
        }
        swap(n,m);
    }
    /*
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++) printf("%d ",a[i][j]);
        puts("");
    }
    */
    ans=t+1;
    if(n<=t)
    {
        for(i=0;i<(1<<m);i++)
        {
            sum=0;
            for(k=1;k<=n;k++)
            {
                tmp=0;
                for(j=0;j<m;j++)
                {
                    if(i&(1<<j))
                    {
                        if(!a[k][j+1]) tmp++;
                    }
                    else
                    {
                        if(a[k][j+1]) tmp++;
                    }
                }
                sum+=min(tmp,m-tmp);
            }
            ans=min(ans,sum);
        }
    }
    else
    {
        for(i=1;i<=n;i++)
        {
            sum=0;
            for(k=1;k<=n;k++)
            {
                tmp=0;
                for(j=1;j<=m;j++)
                {
                    if(a[k][j]!=a[i][j]) tmp++;
                }
                sum+=min(tmp,m-tmp);
            }
            ans=min(ans,sum);
        }
    }
    if(ans>t) printf("-1\n");
    else printf("%d\n",ans);
    return 0;
}

CodeForces 425B Sereja and Table

时间: 2024-12-28 13:26:08

CodeForces 425B Sereja and Table的相关文章

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 ,那么可以枚举

CodeForces 425C Sereja and Two Sequences

题意: 两组数字a和b  如果a[i]等于b[j]  则可将a[i]和b[j]前所有数字删掉  这种操作花费e体力  得到1元钱  或者一次删掉所有数字  这种操作花费等于曾经删除的所有数字个数  做完后得到所有钱  问 一共s体力 可以得到多少钱 思路: dp+二分 由数据可知最多拿到300元钱  因此可以定义  dp[i][j]表示有i元钱时  b串删除到了j处时  a串删到的位置 状态转移为 dp[i][j] = lower_bound ( a[j] , dp[i-1][j-1] + 1

CodeForces 425A Sereja and Swaps

题意: 一串数字  最多可以做k次交换数字  求  最大连续和是多少 思路: n^2暴力枚举所有区间  那么如果要换数字  一定是从区间外拿大数换区间内的小数  优先队列可以完成操作 代码: #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; #define N 201 int n,m,ans; int a[N]; priori

CodeForces 425D Sereja and Squares

题意: 平面上有n个点  问  最多能组成多少个边与坐标轴平行的正方形 思路: 这是一个通过不断二分查找乱搞的题- 首先枚举左下角  然后分别往上往右找左上角和右下角 这时如果发现边长不想等就通过长边长度在短边的方向二分查找最接近的值  不停往上往右延伸 如果发现边长想等了  那么要判断一下对应的左上角坐标出是不是有一个点 怎么判断呢  通过将所有点hash出一个值  然后二分- 反正这题就是各种二分乱搞 - -b  复杂度不好算  大概是n*(同x的点数+同y的点数) 代码: #include

Codeforces Round #243 (Div. 2)——Sereja and Table

看这个问题之前,能够先看看这个论文<一类算法复合的方法>,说白了就是分类讨论,可是这个思想非常重要 题目链接 题意: 首先给出联通块的定义:对于相邻(上下和左右)的同样的数字视为一个联通块 现给一个n*m的仅仅有0和1的矩形和数字k,求出最小反转个数使得总体包含若干个矩形联通块(即每一个联通块均是矩形)(1?≤?n,?m?≤?100; 1?≤?k?≤?10) 假设最小次数比k大,输出-1 分析: 题目的特点是k比較小.也就是说反转的次数比較少,所以能够从这里入手.直接枚举全部的位置肯定是不行了

CodeForces 368B Sereja and Suffixes

Sereja and Suffixes Time Limit: 1000ms Memory Limit: 262144KB This problem will be judged on CodeForces. Original ID: 368B64-bit integer IO format: %I64d      Java class name: (Any) Sereja has an array a, consisting of n integers a1, a2, ..., an. The

Codeforces 425A Sereja and Swaps(暴力枚举)

题目链接:A. Sereja and Swaps 题意:给定一个序列,能够交换k次,问交换完后的子序列最大值的最大值是多少 思路:暴力枚举每一个区间,然后每一个区间[l,r]之内的值先存在优先队列内,然后找区间外假设有更大的值就替换掉. 求出每一个区间的最大值,最后记录下全部区间的最大值 代码: By lab104_yifan, contest: Codeforces Round #243 (Div. 2), problem: (C) Sereja and Swaps, Accepted, #

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

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

CodeForces 380A Sereja and Prefixes

A. Sereja and Prefixes time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Sereja loves number sequences very much. That's why he decided to make himself a new one following a certain algorithm