zoukankan      html  css  js  c++  java
  • hdu1281(棋盘游戏,车的放置)

    Problem Description

    给定一个n * m的棋盘,在棋盘里放尽量多的国际象棋中的车,使他们不能相互攻击 已知有些格子不能放置,问最多能放置多少个车 并计算出必须棋盘上的必须点。

    Input

    第一行有三个数N、M、K(1<N,M<=100 1<K<=N*M),表示了棋盘的高、宽,以及可以放“车”的格子数目。接下来的K行描述了所有格子的信息:每行两个数X和Y,表示了这个格子在棋盘中的位置。

    output

    对输入的每组数据,按照如下格式输出: 
    Board T have C important blanks for L chessmen.

    思路:对于第一个问题 可以把行、列看做二分图的左右节点,共n + m个节点  对所有可放置车的坐标(x, y) 把x,y连边 然后放一个车相当于将x, y两节点匹配 然后就可以用二分图最大匹配来做了

              对于第二个问题,暴力枚举所有(x,y),并将其挖掉,如果匹配数减少了,(x,y)就是必须点。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N = 11000;
    int n, m, q, mat[220];
    bool vis[220], f[220][220];
    
    int head[220],now;
    struct edges{
        int to,next;
    }edge[N<<2];
    void add(int u,int v){ edge[++now] = {v,head[u]}; head[u] = now;}
    
    struct input{
        int x,y;
    }inp[N];
    void init(){
        memset(edge,0,sizeof(edge));
        memset(head,0,sizeof(head)); now = 0;
        memset(mat,0,sizeof(mat));
    }
    
    bool dfs(int x){
        for(int i = head[x]; i; i = edge[i].next){
            int v = edge[i].to;
            if(!vis[v] && !f[x][v]){
                vis[v] = 1;
                if(!mat[v] || dfs(mat[v])){
                    mat[v] = x;
                    return 1;
                }
            }
        }
        return 0;
    }
    
    int main(){
    //    freopen("data.in","r",stdin);
        ios::sync_with_stdio(false);
        int kase = 0;
        while(cin>>n>>m>>q){
            init();
            int x,y;
            for(int i = 1; i <= q; i++){
                cin>>x>>y; y += n;
                inp[i] = {x, y};
                add(x,y);// add(y,x);
            }
            int ans = 0;
            for(int i = 1; i <= n; i++){
                memset(vis,0,sizeof(vis));
                if(dfs(i)) ans++;
            }
            int tot = 0;
            for(int i = 1; i <= q; i++){
                f[inp[i].x][inp[i].y] = f[inp[i].y][inp[i].x] = 1;  //枚举每个可放置的点 
                memset(mat,0,sizeof(mat));
                int cnt = 0;                                      //cnt记录每次挖去一个点后的匹配数 
                for(int j = 1; j <= n; j++){
                    memset(vis,0,sizeof(vis));
                    if(dfs(j)) cnt++;
                }
                if(cnt < ans) tot++;
                f[inp[i].x][inp[i].y] = 0;
            }
            printf("Board %d have %d important blanks for %d chessmen.
    ",++kase,tot,ans);
        }
        return 0;
    }

      

  • 相关阅读:
    JavaScript函数节流与函数去抖
    AngularJS 中文资料+工具+库+Demo 大搜集
    一个意想不到的Javascript内存泄漏
    mac添加Chromedriver
    selenium3+python自动化1——input标签上传文件
    python笔记1——xml文件的创建,读写,与增删改查
    C# 单例模式
    java的byte数组转换成在[0,255]范围内
    【转载】Stack Overflow: The Architecture
    C# 号码归属地查询算法(根据Android来电归属地二进制文件查询修改)
  • 原文地址:https://www.cnblogs.com/Rorshach/p/8681674.html
Copyright © 2011-2022 走看看