zoukankan      html  css  js  c++  java
  • poj 1719 Shooting Contest

    http://poj.org/problem?id=1719

    Shooting Contest
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 4135   Accepted: 1521   Special Judge

    Description

    Welcome to the Annual Byteland Shooting Contest. Each competitor will shoot to a target which is a rectangular grid. The target consists of r*c squares located in r rows and c columns. The squares are coloured white or black. There are exactly two white squares and r-2 black squares in each column. Rows are consecutively labelled 1,..,r from top to bottom and columns are labelled 1,..,c from left to right. The shooter has c shots. 

    A volley of c shots is correct if exactly one white square is hit in each column and there is no row without white square being hit. Help the shooter to find a correct volley of hits if such a volley exists. 
    Example 
    Consider the following target: 

    Volley of hits at white squares in rows 2, 3, 1, 4 in consecutive columns 1, 2, 3, 4 is correct. 
    Write a program that: verifies whether any correct volley of hits exists and if so, finds one of them.

    Input

    The first line of the input contains the number of data blocks x, 1 <= x <= 5. The following lines constitute x blocks. The first block starts in the second line of the input file; each next block starts directly after the previous one. 

    The first line of each block contains two integers r and c separated by a single space, 2 <= r <= c <= 1000. These are the numbers of rows and columns, respectively. Each of the next c lines in the block contains two integers separated by a single space. The integers in the input line i + 1 in the block, 1 <= i <= c, are labels of rows with white squares in the i-th column. 

    Output

    For the i-th block, 1 <= i <= x, your program should write to the i-th line of the standard output either a sequence of c row labels (separated by single spaces) forming a correct volley of hits at white squares in consecutive columns 1, 2, ..., c, or one word NO if such a volley does not exists.

    Sample Input

    2
    4 4
    2 4
    3 4
    1 3
    1 4
    5 5
    1 5
    2 4
    3 4
    2 4
    2 3
    

    Sample Output

    2 3 1 4
    NO


    题意比较难理解,题意弄懂后这道题就比较简单,套用匈牙利算法求最大匹配

    题目大意:r*c的矩阵,矩阵由白格子和黑格子组成,每一列有两个格子是白色的剩下的为黑色,每一列射击一发子弹击中白色格子,问是否所有行都有白色格子被击中

    数据分析:
    2//数据组数
    4 4//行r  列c
    2 4//第1列的第2行和第4行是白色格子
    3 4//第2列的第3行和第4行是白色格子
    1 3//第3列的第1行和第3行是白色格子
    1 4// ...
    1.如果 r > c , c列射击完后仍会有行没有被射击过;
    2.要从每一列开始射击并射中白色格子,即将行r和列c作为X,Y集合,白色格子部分进行匹配,得到最大匹配值ans
    1>如果ans==r
    (1)如果每一列都有匹配(即都能射中某一行的白色格子)就输出与该列匹配的行(即该列击中的的白色格子所在的行)
    (2)如果某一列没有找到匹配的格子,那个只要在该行任意选择一个白色的格子就可以了,输出该白色格子所在的行
    2>如果ans>r或者ans<r都无法满足每行都被射击过

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<stdlib.h>
    #include<queue>
    #include<algorithm>
    #define INF 0x3f3f3f3f
    #define N 1010
    
    using namespace std;
    
    int G[N][N], vis[N], used[N];
    int r, c;
    
    bool Find(int u)
    {
        int i;
        for(i = 1 ; i <= c ; i++)
        {
            if(!vis[i] && G[u][i])
            {
                vis[i] = 1;
                if(!used[i] || Find(used[i]))
                {
                    used[i] = u;
                    return true;
                }
            }
        }
        return false;
    }//匈牙利
    
    int main()
    {
        int a, b, i, t;
        scanf("%d", &t);
        while(t--)
        {
            scanf("%d%d", &r, &c);
            if(r > c)
            {
                printf("NO
    ");
                continue;
            }//如果 r > c , c列射击完后仍会有行没有被射击过
            memset(G, 0, sizeof(G));
            for(i = 1 ; i <= c ; i++)
            {
                scanf("%d%d", &a, &b);
                G[a][i] = G[b][i] = 1;//第i列个第a行和第b行是白色格子
            }
            memset(used, 0, sizeof(used));
            int ans = 0;
            for(i = 1 ; i <= r ; i++)
            {
                memset(vis, 0, sizeof(vis));
                if(Find(i))
                    ans++;
            }
            if(ans == r)
            {
                for(i = 1 ; i <= c ; i++)
                {
                    if(used[i] != 0)//如果每一列都有匹配(即都能射中某一行的白色格子)就输出与该列匹配的行(即该列击中的的白色格子所在的行)
                        printf("%d ", used[i]);
                    else
                    {
                        for(int j = 1 ; j <= r ; j++)
                        {
                            if(G[j][i])
                            {
                                printf("%d ", j);
                                break;
                            }
                        }
                    }//如果某一列没有找到匹配的格子,那个只要在该行任意选择一个白色的格子就可以了,输出该白色格子所在的行;
                }
                 printf("
    ");
            }
            else//如果ans>r或者ans<r都无法满足每行都被射击过
                printf("NO
    ");
        }
        return 0;
    }


     


  • 相关阅读:
    老年玩家每日水题(完结)
    51node1256 乘法匿元(扩展欧几里得)
    初识Springboot
    Springboot实现登录功能
    使用SMM框架开发企业级应用-----过滤器实现登录拦截
    使用SMM框架开发企业级应用-----mvc文件上传和下载
    使用SMM框架开发企业级应用-----MVC异常处理
    使用SMM框架开发企业级应用-----MVC参数传递
    使用SMM框架开发企业级应用-----MVC方法返回值类型
    使用SMM框架开发企业级应用-----基础配置
  • 原文地址:https://www.cnblogs.com/qq2424260747/p/4820012.html
Copyright © 2011-2022 走看看