zoukankan      html  css  js  c++  java
  • toj 4061 矩阵攻击(最大独立集)

    题目:

    给定一个01 矩阵,其中你可以在0的位置放置攻击装置。每一个攻击装置 (x,y) 都可以按照“日”字攻击其周围八个位置(x−1,y−2),(x−2,y−1),(x+1,y−2),(x+2,y−1),(x−1,y+2), (x−2,y+1),(x+1,y+2),(x+2,y+1)。

    求在装置不相互攻击的情况下,最多可以放置多少个装置。

    输入

    第一行一个整数 N,表示矩阵大小为 N*N。接下来 N 行是一个长度为N的01 串,表示矩阵。(N <= 200)

    输出

    一个整数,表示在装置不相互攻击的情况下最多可以放置多少个装置。

    样例输入

    3
    010 
    000 
    100

    样例输出

    4

    分析:通过画图来分析,假设在左上角放置攻击装置,忽略障碍,标记出可以其他可以放置跟不可以放置装置的位置,会发现他们是交替出现的;如果把x和y坐标和为奇数的位置归为一类,为偶数的归为一类,则在同类位置间任意放置装置时不会相互攻击,在两类位置分别放置攻击装置时,可能相互攻击。至此,此题二分图的特征已经相当明显了,是个求解最大独立集的问题。
    代码如下(通过此题发现vector存图好慢,跟手写的结构体相比,差了不止一点,以后还是尽量少用vector存图):
    #include <cstdio>
    #include <cstring>
    using namespace std;
    #define N 205
    
    //发现用vector 存图好慢呀
    struct Edge{
        int v, next;
    }edge[N*N*8];
    int Ecnt;
    int head[N*N];
    
    char mp[N][N];
    int id[N][N];
    int n;
    int go[4][2] = {{-1,2}, {-2,1}, {1,2}, {2,1}};
    
    int link[N*N];
    bool visited[N*N];
    
    void add(int u, int v)
    {
        edge[Ecnt].v = v, edge[Ecnt].next = head[u], head[u] = Ecnt++;
        edge[Ecnt].v = u, edge[Ecnt].next = head[v], head[v] = Ecnt++;
    }
    
    bool find(int u)
    {
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].v;
            if(visited[v]) continue;
            visited[v] = true;
            if(link[v] == -1 || find(link[v]))
            {
                link[v] = u;
                return true;
            }
        }
        return false;
    }
    
    int solve()
    {
        int m = (n*n+1)>>1, c = n*n;
        memset(link, -1, sizeof(link));
        int res = 0;
        for(int i = 0; i < m; i++)
        {
            memset(visited, 0, sizeof(visited));
            if(find(i)) res++;
        }
        return res;
    }
    
    int main()
    {
        while(~scanf("%d", &n))
        {
            int m = (n*n+1)/2;
            memset(head, -1, sizeof(head));
            Ecnt = 0;
            for(int i = 0; i < n; i++)  scanf("%s", mp[i]);
            int cnt = 0;
            for(int i = 0; i < n; i++)
                for(int j = 0; j < n; j++)
                    cnt += (mp[i][j] == '1');
            int c0 = 0, c1 = (n*n+1)>>1;
            for(int i = 0; i < n; i++)
                for(int j = 0; j < n; j++)
                    id[i][j] = ((i+j)&1) ? c1++ : c0++;
            for(int i = 0; i < n; i++)
            {
                for(int j = 0; j < n; j++)
                {
                    if(mp[i][j] == '0')
                    {
                        int nx, ny;
                        for(int k = 0; k < 4; k++)
                        {
                            nx = i+go[k][0], ny = j+go[k][1];
                            if(nx >= 0 && nx < n && ny >= 0 && ny < n && mp[nx][ny] == '0')
                                add(id[i][j], id[nx][ny]);
                        }
                    }
                }
            }
            printf("%d
    ", n*n-cnt-solve());
        }
        return 0;
    }
     
  • 相关阅读:
    c#自动更新+安装程序的制作
    VS2013项目受源代码管理向源代码管理注册此项目时出错
    WinDbg配置和使用基础
    InstallShield Limited Edition for Visual Studio 2013 图文教程(教你如何打包.NET程序)
    PowerDesigner 如何生成数据库更新脚本
    用户故事(User Story)
    Troubleshooting Record and Playback issues in Coded UI Test
    Coded UI
    compare two oracle database schemas
    How to: Use Schema Compare to Compare Different Database Definitions
  • 原文地址:https://www.cnblogs.com/beisong/p/4456462.html
Copyright © 2011-2022 走看看