zoukankan      html  css  js  c++  java
  • HDU1045 Fire NetFire Net 最大团

    题意:给定一个棋盘,如果在某一个点放置棋子,那么这个棋子出现的行和列都不够有其他的棋子,除非他们之间有墙相隔。现在给定一个含有墙的和空地的棋盘,问最多能够放置多少棋子。

    解法:将所有为"."的点保存起来,如果两个点不在同一行且不在同一列,那么在两个点之间连一条边,否则判定两点之间是否有墙相隔,有的话连边,否则不连,最后求一个最大团即可。

    代码如下:

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    
    int N, nd[20], idx, G[20][20];
    char mp[10][10];
    
    bool check(int a, int b) {
        int x1 = nd[a]/N, y1 = nd[a]%N;
        int x2 = nd[b]/N, y2 = nd[b]%N;
        if (x1 != x2 && y1 != y2) return true;
        if (x1 == x2) { // 如果是在同一行
            for (int i = y1+1; i < y2; ++i) {
                if (mp[x1][i] == 'X') {
                    return true;
                }
            }
        }
        else if (y1 == y2) {
            for (int i = x1+1; i < x2; ++i) {
                if (mp[i][y1] == 'X') {
                    return true;
                }
            }
        }
        return false;
    }
    
    void build() {
        memset(G, 0, sizeof (G));
        for (int i = 0; i < idx; ++i) {
            for (int j = i+1; j < idx; ++j) {
                G[i][j] = G[j][i] = check(i, j);
            }
        }
    }
    
    int ret, cnt[20], st[20];
    
    void dfs(int x, int num) {
        for (int i = x+1; i < idx; ++i) {
            if (!G[x][i]) continue;
            if (cnt[i] + num <= ret) return;
            int flag = true;
            for (int j = 0; j < num; ++j) {
                if (!G[i][st[j]]) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                st[num] = i;
                dfs(i, num+1);
            }
        }
        if (num > ret) {
            ret = num;
        }
    }
    
    int query() {
        ret = 0;
        for (int i = idx-1; i >= 0; --i) {
            st[0] = i;
            dfs(i, 1);
            cnt[i] = ret;
        }
        return ret;
    }
    
    int main() {
        while (scanf("%d", &N), N) {
            idx = 0;
            for (int i = 0; i < N; ++i) {
                scanf("%s", mp[i]);
                for (int j = 0; j < N; ++j) {
                    if (mp[i][j] == '.') {
                        nd[idx++] = i*N+j;
                    }
                }
            }
            build();
            printf("%d\n", query());
        }
        return 0;
    }
  • 相关阅读:
    BZOJ 4033: [HAOI2015]树上染色 (树形DP)
    BZOJ 1820: [JSOI2010]Express Service 快递服务 DP
    BZOJ 4664: Count 插块DP
    BZOJ 1899: [Zjoi2004]Lunch 午餐 DP
    BZOJ 4559 [JLoi2016]成绩比较 (DP+拉格朗日插值)
    BZOJ1485 [HNOI2009] 有趣的数列 (卡特兰数)
    BZOJ 2111 / Luogu P2606 [ZJOI2010]排列计数
    20190915模拟赛
    深海机器人问题
    太空飞行计划问题
  • 原文地址:https://www.cnblogs.com/Lyush/p/2996712.html
Copyright © 2011-2022 走看看