校内训练0611 矩阵

【题目大意】

给一个n*n的矩阵,每个位置为0或1。每次可以选择一行和一列,把那列完全赋值为那行的值。求最少多少步使得全为1.

无解输出-1。

n <= 1000

【题解】

发现只有全空才是无解,否则考虑构造。

每一列,只要有0的格子都需要被赋值1次,所以设有x列有含有0的格子,则至少要赋值x次。

现在我们就需要一个全1的行来给这些有0的列赋值。

考虑构造一个全1的行。我们枚举第i行,假装要把他弄成全1的。

设第i行的0的数量为y,那么考虑第i列是否含有1,如果含有1那么就可以用含有1的那列的那行给第i行所有0的地方赋值,需要y步。

如果第i列不含有1,我们要花1次操作给第i列搞个1出来,所以答案是y+1步。

取最小值即可。

这签到题我怎么没做出来啊。。

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 1e3 + 10;
const int mod = 1e9+7;

# define RG register
# define ST static

int n, a[M];
char mp[M][M];
bool hv[M];

int main() {
//    freopen("matrix.in", "r", stdin);
//    freopen("matrix.out", "w", stdout);
    cin >> n;
    for (int i=1; i<=n; ++i) scanf("%s", mp[i]+1);
    bool all = 1;
    for (int i=1; i<=n; ++i)
        for (int j=1; j<=n; ++j)
            all &= (mp[i][j] == ‘.‘);
    if(all) {
        puts("-1");
        return 0;
    }

    int ans = 0;
    for (int i=1; i<=n; ++i) {
        bool have = 0;
        for (int j=1; j<=n; ++j) {
            if(mp[j][i] == ‘.‘) {
                have = 1;
                break;
            }
        }
        ans += have;
        for (int j=1; j<=n; ++j)
            if(mp[j][i] == ‘#‘) hv[i] = 1;
    }

    int tmp = 1e9;
    for (int i=1; i<=n; ++i) {
        // for one line
        int cur = 0;
        for (int j=1; j<=n; ++j) cur += (mp[i][j] == ‘.‘);
        if(cur == 0 || hv[i]) tmp = min(tmp, cur);
        else tmp = min(tmp, cur+1);
    }
    cout << ans + tmp;

    return 0;
}

时间: 2024-11-08 02:03:37

校内训练0611 矩阵的相关文章

校内训练0611 围墙

[题目大意] 围墙可以看成是一个长度为 n 的括号序列,与此同时还有一个长度为 n 的排列 P,一个围墙被称为稳的,当且仅当: (1)这个括号序列是合法的. (2)构造一张 n 个点的图, 当且仅当第 i 个位置是左括号时, 点 i 向点 Pi 连边,最后形成的图必须满足每个点度数均为一. 保证对于任意 i 有 Pi!=i. 求一种合法方案.保证有解. n <= 100 [题解] 我们考虑这是个置换,所以一定形成了很多不相交的环. 对于每个环,我们只能选一段.不选.选一段.不选这样交替下去. 显

「csp校内训练 2019-10-24」解题报告

「csp校内训练 2019-10-24」解题报告 T1.猴猴吃苹果 \(Description\) 猴猴最喜欢在树上玩耍,一天猴猴又跳上了一棵树,这棵树有 \(N \ (N \leq 50000)\) 个苹果,每个苹果有一个编号,分别为 \(0\) ~ \(N - 1\) 它们之间由 \(N-1\) 个树枝相连,猴猴可以从树枝的一端爬到树枝的另一端,所以猴猴可以从任意一个苹果的位置出发爬到任意猴猴想去的苹果的位置. 猴猴开始在编号为 \(K \ (K < N)\) 的苹果的位置,并且把这个苹果吃

「csp校内训练 2019-10-30」解题报告

「csp校内训练 2019-10-30」解题报告 T1.树 题目链接(逃) \(Description\): 现在有一棵树,共 \(N\) 个节点. 规定:根节点为 \(1\) 号节点,且每个节点有一个点权. 现在,有 \(M\) 个操作需要在树上完成,每次操作为下列三种之一: \(1 \ x \ a\):操作 \(1\),将节点 \(x\) 点权增加 \(a\). \(2 \ x \ a\):操作 \(2\),将以节点 \(x\) 为根的子树中所有点的权值增加 \(a\). \(3 \ x\)

2017-3-3校内训练

hzwer出丧题虐人啦 ACM赛制 4/7 A.恼人的青蛙 题目大意:给定N*M矩阵上K个点,定义一条合法路径为从矩形外一点沿一条直线穿过矩形,每次走相同长度且在矩形内每步都要踩在给定点上,问经过给定点最多的路径经过几个点(若小于3输出0)(N,M,K<=5000). 思路:把点按横坐标第一关键字纵坐标第二关键字排序,f[i][j]表示有一条到i的路径,i上一个点是j,此时路径经过点数,每次确定i,j后就可以根据i,j算出j再前一个点的坐标,直接转移,复杂度O(K^2).评测机极慢稍微卡卡常才能

20170908校内训练

题意: 学过博弈论的同学都知道Nim游戏后手必胜的条件是异或和为0给定一棵树 ,支持修改单点点权,询问链上异或和 预处理每个点到根的路径的异或和由于异或的特殊性质,在求链x->y的异或和的时候,我们只需要知道x到根的异或和,y到根的异或和,将他们异或起来,最后异或上lca处的值即可. 如图,查询两个灰色节点的异或和 如果一个点的值被修改,那么它和它的子树到根的路径的异或和的值都会被修改 所以,我们维护一棵dfs序为下标的线段树,线段树的sum意义是它的区间的值的异或和 修改一个值,如果该值为x,

2017-4-7校内训练

丧病hzwer的ctsc训练赛 My AC:3/4 A.[Ctsc2014]企鹅QQ 思路:乱hash,我比较菜,写的丑代码各种WA+TLE,好久才A掉. #include<cstdio> #include<algorithm> using namespace std; #define ll long long #define MN 200 #define MX 6000000 #define MM 9000001 #define MOD1 890123798112473LL st

校内训练0602 习题exercise

[题目大意] f(i)=((Af(i-1)+B)/(Cf(i-1)+D)) mod P. 给出f(0), A, B, C, D, P, n,求f(n). 多组数据T<=1e4 n<=1e18, P <= 1e9, |f(0)|,|A|,|B|,|C|,|D| <= 1e9 保证任何时候存在逆元. [题解] 首先我们有一种O(TP)的做法:找循环节. 考场上因为数据原因是可以AC的.. # include <map> # include <stdio.h> #

20170910校内训练

CCT 最近学校又发了n本五三题霸,BBS看到后十分高兴.但是,当他把五三拿到手后才发现,他已经刷过这些书了!他又认真地看了一会儿,发现新发的这些五三是2017版的,而他刷的是2016版的.现在他想找出所有他没有刷过的题来刷.每本五三都有m道题,并且它的特征(即它和去年版本的五三的差距)可以用一个m位二进制数来代表,二进制位上的1代表该题不同,0代表该题相同.比如4(100)就代表题目3和去年的有不同.5(101)就代表题目1和题目3和去年的有不同.而BBS热衷于给自己找麻烦,他要选择连续一段的

【三中校内训练】旅行

[题解] 显然的这是一道树形DP的题目 这里令f[i][0]为从i出发向以它为根的子树里走直到不能走的最大.最小价值 (不能走是什么自己阅读题目) 令s为x的儿子,w[i][j]为i和j之间的边的长度,则 f[x][0]=max(f[s][1]+w[s][i]) f[x][1]=min(f[s][0]+w[s][i]) 显然的通过这种方法,我们可以得到60分 可是,如何优化到线性呢 我们考虑一个节点x,x向某条边走的情况出现了很多次,浪费了很多时间 我们定义h[x][0/1]为从x出发,经过x的