codeforces Gym-101246C

题意给你一个n*m的矩阵,矩阵有0点,有1点,你放一个雷,就会让和雷所在的同一行和同一列的所有1变成0.n和m小于,问最少放几个雷?
思路我一开始想了个二分图,想行是一个集合,列是一个集合,然后每一个点去建一条边,想了想完美匹配的东西,但是发现。。。好像不行。。。然后这是个搜索。因为你看他不到25位,就可以状压成一个int值。然后不断的搞来搞去。
1,先把矩阵的每一行处理成一个int值。
2,然后搜索,搜索的方向就是这一行放雷还是不放雷,如果放雷的话,看看还有那一些列需要炸。(这是一个状态)先处理了每一行,然后上一个状态和当前行没放雷的状态|(或)操作一下就可以了。(PS:如果你放雷的话,这一行就没有1,你就可以直接用上一个状态,不用或了)
3,当你放到最后一行的时候,你需要知道最终状态有多少个雷,这样一般来讲是要除2然后%2,但是这样会t,所以先给他预处理一下,怎么预处理呢?就是用lowbit去,(如果不会可以看一看树状数组)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
typedef long long LL;

int n , m;
int f[(int)4e7] , _min,  P[40];
char s[50][50];

void dfs(int d , int a , int b)//d 行, 放了a个雷 , 列的状态
{
    if(d > n){
        b = f[b];
        _min = min(_min , a + (max(a , b) - a));
    }
    else{
        dfs(d + 1 , a + 1 , b);
        dfs(d + 1 , a , b | P[d]);
    }
}

int main()
{
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    for(int i = 1 ; i <= (1 << 25) ; i++) f[i] = f[i ^ (i & (-i))] + 1;//这个是lowbit
    while(~scanf("%d %d",&n , &m)){
        _min = n * m;
        for(int i = 1 ; i <= n ; i++){
            for(int j = 1 ; j <= m ; j++) scanf(" %c",&s[i][j]);
        }
        for(int i = 1 ; i <= n ; i++){
            int sum = 0 , ans = 1;
            for(int j = m ; j >= 1 ; j--){
                if(s[i][j] == '*') sum += ans;
                ans *= 2;
            }
            P[i] = sum;
        }
        dfs(1 , 0 , 0);
        printf("%d\n",_min);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值