• hdu1045


    题目链接

    左边白方格里放小球,满足同一行、列只有一个(被黑块隔开)。问最多放多少个球。

    ------------------------------------------------------------------------------------------------------------

    从贪心类别看到这个题的,读完题后只能想到枚举的解法 ==。智商有限。

    看了题解后才知道怎么贪心,还有一个最大二分匹配的解法。

    1.枚举

    依次判断每个格子能不能放小球,如果能则返回 max{dfs(放),dfs(不放)},否则返回dfs(不放).

    #define _CRT_SECURE_NO_DEPRECATE
    #include <set>
    #include <map>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <vector>
    #include <string>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    
    #define MAX(a,b) ((a)>=(b)?(a):(b))
    #define MIN(a,b) ((a)<=(b)?(a):(b))
    #define OO 0x0fffffff
    typedef long long LL;
    using namespace std;
    typedef pair<int, int> int2;
    const int dir[4][2] = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };
    char status[8][8];
    int2 dots[16];
    int dotcnt;
    int n;
    
    int dfs(int depth){
        if (depth == dotcnt){
            int ret = 0;
            for (int i = 0; i<n; i++) for (int j = 0; j<n; j++) if (status[i][j] == '*') ret++;
            return ret;
        }
        int x = dots[depth].first;
        int y = dots[depth].second;
        bool flag = true;
    
        for (int i = 0; i<4; i++){
            for (int j = 1; flag; j++){
                int tx = x + dir[i][0] * j;
                int ty = y + dir[i][1] * j;
                if (tx<0 || ty<0 || tx >= n || ty >= n) break;
                if (status[tx][ty] == 'X') break;
                if (status[tx][ty] == '*') { flag = false; break; }
            }
        }
        int no = dfs(depth + 1);
        if (flag) {
            status[x][y] = '*';
            int yes = dfs(depth + 1);
            status[x][y] = '.';
            return max(no,yes);
        }
        else return no;
    }
    
    int main(){
        while (scanf("%d", &n), n){
            dotcnt = 0;
            for (int i = 0; i<n; i++) {
                scanf("%s", status[i]);
                for (int j = 0; j<n; j++)
                     if (status[i][j] != 'X') dots[dotcnt++] = make_pair(i, j);
            }
            printf("%d
    ", dfs(0));
        }
        return 0;
    }

    2. 贪心

    统计每个白块所在行和列的连通区域的面积s,从第一排开始处理,找到s最小的块,标记,继续找第一排中最小的,如果没有了则挪到下一排。

    3. 二分匹配

    现在还没复习到二分图,只写一下二分图的构造:

    a. 列收缩。所有列中每一个联通的白块看做一个点。记该序列为A;

    b. 行收缩。得到序列B;

    c. 连边。对所有(a,b)属于(A,B),如果ab相交则连一条边

    接下来就是最大二分匹配了

  • 相关阅读:
    12.12 怀北滑雪场滑雪记
    datetime类型offset-aware与offset-navie
    Django-models中的choise
    什么是__name__()
    单机Ubuntu安装第二个Mysql服务
    Ubuntu下的Python安装
    设置mysql允许外网访问
    Ubuntu初次设置root密码
    使用VMware+Ubuntu,无法切换大小写的异常处理
    XShell/Xftp 无法连接 Ubuntu20
  • 原文地址:https://www.cnblogs.com/redips-l/p/7243507.html
Copyright © 2020-2023  润新知